create-pxlr 1.0.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 (153) hide show
  1. package/README.md +160 -0
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.js +264 -0
  4. package/package.json +51 -0
  5. package/templates/blog/frontend/app/blog/[slug]/page.tsx +175 -0
  6. package/templates/blog/frontend/app/blog/page.tsx +102 -0
  7. package/templates/blog/frontend/app/components/footer.tsx +21 -0
  8. package/templates/blog/frontend/app/components/header.tsx +45 -0
  9. package/templates/blog/frontend/app/globals.css +30 -0
  10. package/templates/blog/frontend/app/layout.tsx +38 -0
  11. package/templates/blog/frontend/app/lib/cms.ts +71 -0
  12. package/templates/blog/frontend/app/page.tsx +155 -0
  13. package/templates/blog/frontend/next.config.ts +16 -0
  14. package/templates/blog/frontend/package.json +24 -0
  15. package/templates/blog/frontend/postcss.config.mjs +7 -0
  16. package/templates/blog/frontend/tsconfig.json +23 -0
  17. package/templates/blog/pxlr-cms/README.md +188 -0
  18. package/templates/blog/pxlr-cms/docker-compose.yml +132 -0
  19. package/templates/blog/pxlr-cms/nginx/nginx.conf +107 -0
  20. package/templates/blog/pxlr-cms/packages/admin/.dockerignore +4 -0
  21. package/templates/blog/pxlr-cms/packages/admin/.env.example +2 -0
  22. package/templates/blog/pxlr-cms/packages/admin/Dockerfile +19 -0
  23. package/templates/blog/pxlr-cms/packages/admin/next-env.d.ts +6 -0
  24. package/templates/blog/pxlr-cms/packages/admin/next.config.ts +22 -0
  25. package/templates/blog/pxlr-cms/packages/admin/package.json +63 -0
  26. package/templates/blog/pxlr-cms/packages/admin/pnpm-lock.yaml +5748 -0
  27. package/templates/blog/pxlr-cms/packages/admin/postcss.config.mjs +9 -0
  28. package/templates/blog/pxlr-cms/packages/admin/src/app/content/[id]/page.tsx +503 -0
  29. package/templates/blog/pxlr-cms/packages/admin/src/app/content/layout.tsx +7 -0
  30. package/templates/blog/pxlr-cms/packages/admin/src/app/content/new/page.tsx +424 -0
  31. package/templates/blog/pxlr-cms/packages/admin/src/app/content/page.tsx +191 -0
  32. package/templates/blog/pxlr-cms/packages/admin/src/app/globals.css +132 -0
  33. package/templates/blog/pxlr-cms/packages/admin/src/app/layout.tsx +25 -0
  34. package/templates/blog/pxlr-cms/packages/admin/src/app/login/page.tsx +119 -0
  35. package/templates/blog/pxlr-cms/packages/admin/src/app/media/layout.tsx +7 -0
  36. package/templates/blog/pxlr-cms/packages/admin/src/app/media/page.tsx +362 -0
  37. package/templates/blog/pxlr-cms/packages/admin/src/app/page.tsx +184 -0
  38. package/templates/blog/pxlr-cms/packages/admin/src/app/profile/layout.tsx +7 -0
  39. package/templates/blog/pxlr-cms/packages/admin/src/app/profile/page.tsx +206 -0
  40. package/templates/blog/pxlr-cms/packages/admin/src/app/schemas/[name]/page.tsx +312 -0
  41. package/templates/blog/pxlr-cms/packages/admin/src/app/schemas/layout.tsx +7 -0
  42. package/templates/blog/pxlr-cms/packages/admin/src/app/schemas/page.tsx +210 -0
  43. package/templates/blog/pxlr-cms/packages/admin/src/app/settings/layout.tsx +7 -0
  44. package/templates/blog/pxlr-cms/packages/admin/src/app/settings/page.tsx +178 -0
  45. package/templates/blog/pxlr-cms/packages/admin/src/components/editor/media-picker.tsx +202 -0
  46. package/templates/blog/pxlr-cms/packages/admin/src/components/editor/rich-text-editor.tsx +387 -0
  47. package/templates/blog/pxlr-cms/packages/admin/src/components/layout/auth-layout.tsx +43 -0
  48. package/templates/blog/pxlr-cms/packages/admin/src/components/layout/header.tsx +79 -0
  49. package/templates/blog/pxlr-cms/packages/admin/src/components/layout/sidebar.tsx +68 -0
  50. package/templates/blog/pxlr-cms/packages/admin/src/components/providers.tsx +29 -0
  51. package/templates/blog/pxlr-cms/packages/admin/src/components/schema-code-generator.tsx +326 -0
  52. package/templates/blog/pxlr-cms/packages/admin/src/components/ui/avatar.tsx +49 -0
  53. package/templates/blog/pxlr-cms/packages/admin/src/components/ui/button.tsx +55 -0
  54. package/templates/blog/pxlr-cms/packages/admin/src/components/ui/dropdown-menu.tsx +194 -0
  55. package/templates/blog/pxlr-cms/packages/admin/src/components/ui/input.tsx +24 -0
  56. package/templates/blog/pxlr-cms/packages/admin/src/components/ui/label.tsx +25 -0
  57. package/templates/blog/pxlr-cms/packages/admin/src/components/ui/toast.tsx +127 -0
  58. package/templates/blog/pxlr-cms/packages/admin/src/components/ui/toaster.tsx +35 -0
  59. package/templates/blog/pxlr-cms/packages/admin/src/components/ui/use-toast.ts +187 -0
  60. package/templates/blog/pxlr-cms/packages/admin/src/lib/api.ts +96 -0
  61. package/templates/blog/pxlr-cms/packages/admin/src/lib/i18n/context.tsx +60 -0
  62. package/templates/blog/pxlr-cms/packages/admin/src/lib/i18n/translations.ts +317 -0
  63. package/templates/blog/pxlr-cms/packages/admin/src/lib/store/auth.ts +51 -0
  64. package/templates/blog/pxlr-cms/packages/admin/src/lib/utils.ts +29 -0
  65. package/templates/blog/pxlr-cms/packages/admin/tailwind.config.ts +57 -0
  66. package/templates/blog/pxlr-cms/packages/admin/tsconfig.json +27 -0
  67. package/templates/blog/pxlr-cms/packages/api/.env.example +23 -0
  68. package/templates/blog/pxlr-cms/packages/api/Dockerfile +26 -0
  69. package/templates/blog/pxlr-cms/packages/api/package.json +42 -0
  70. package/templates/blog/pxlr-cms/packages/api/src/config.ts +39 -0
  71. package/templates/blog/pxlr-cms/packages/api/src/database/index.ts +60 -0
  72. package/templates/blog/pxlr-cms/packages/api/src/database/init.sql +258 -0
  73. package/templates/blog/pxlr-cms/packages/api/src/database/redis.ts +95 -0
  74. package/templates/blog/pxlr-cms/packages/api/src/database/seed.sql +78 -0
  75. package/templates/blog/pxlr-cms/packages/api/src/index.ts +157 -0
  76. package/templates/blog/pxlr-cms/packages/api/src/modules/auth/routes.ts +256 -0
  77. package/templates/blog/pxlr-cms/packages/api/src/modules/content/routes.ts +385 -0
  78. package/templates/blog/pxlr-cms/packages/api/src/modules/media/routes.ts +312 -0
  79. package/templates/blog/pxlr-cms/packages/api/src/modules/realtime/handler.ts +228 -0
  80. package/templates/blog/pxlr-cms/packages/api/src/modules/schema/routes.ts +284 -0
  81. package/templates/blog/pxlr-cms/packages/api/src/modules/versions/routes.ts +70 -0
  82. package/templates/blog/pxlr-cms/packages/api/tsconfig.json +24 -0
  83. package/templates/blog/pxlr-cms/packages/shared/package.json +14 -0
  84. package/templates/blog/pxlr-cms/packages/shared/src/types/index.ts +139 -0
  85. package/templates/blog/pxlr-cms/packages/shared/tsconfig.json +18 -0
  86. package/templates/clean/pxlr-cms/README.md +188 -0
  87. package/templates/clean/pxlr-cms/docker-compose.yml +132 -0
  88. package/templates/clean/pxlr-cms/nginx/nginx.conf +107 -0
  89. package/templates/clean/pxlr-cms/packages/admin/.dockerignore +4 -0
  90. package/templates/clean/pxlr-cms/packages/admin/.env.example +2 -0
  91. package/templates/clean/pxlr-cms/packages/admin/Dockerfile +19 -0
  92. package/templates/clean/pxlr-cms/packages/admin/next-env.d.ts +6 -0
  93. package/templates/clean/pxlr-cms/packages/admin/next.config.ts +22 -0
  94. package/templates/clean/pxlr-cms/packages/admin/package.json +63 -0
  95. package/templates/clean/pxlr-cms/packages/admin/pnpm-lock.yaml +5748 -0
  96. package/templates/clean/pxlr-cms/packages/admin/postcss.config.mjs +9 -0
  97. package/templates/clean/pxlr-cms/packages/admin/src/app/content/[id]/page.tsx +503 -0
  98. package/templates/clean/pxlr-cms/packages/admin/src/app/content/layout.tsx +7 -0
  99. package/templates/clean/pxlr-cms/packages/admin/src/app/content/new/page.tsx +424 -0
  100. package/templates/clean/pxlr-cms/packages/admin/src/app/content/page.tsx +191 -0
  101. package/templates/clean/pxlr-cms/packages/admin/src/app/globals.css +132 -0
  102. package/templates/clean/pxlr-cms/packages/admin/src/app/layout.tsx +25 -0
  103. package/templates/clean/pxlr-cms/packages/admin/src/app/login/page.tsx +119 -0
  104. package/templates/clean/pxlr-cms/packages/admin/src/app/media/layout.tsx +7 -0
  105. package/templates/clean/pxlr-cms/packages/admin/src/app/media/page.tsx +362 -0
  106. package/templates/clean/pxlr-cms/packages/admin/src/app/page.tsx +184 -0
  107. package/templates/clean/pxlr-cms/packages/admin/src/app/profile/layout.tsx +7 -0
  108. package/templates/clean/pxlr-cms/packages/admin/src/app/profile/page.tsx +206 -0
  109. package/templates/clean/pxlr-cms/packages/admin/src/app/schemas/[name]/page.tsx +312 -0
  110. package/templates/clean/pxlr-cms/packages/admin/src/app/schemas/layout.tsx +7 -0
  111. package/templates/clean/pxlr-cms/packages/admin/src/app/schemas/page.tsx +210 -0
  112. package/templates/clean/pxlr-cms/packages/admin/src/app/settings/layout.tsx +7 -0
  113. package/templates/clean/pxlr-cms/packages/admin/src/app/settings/page.tsx +178 -0
  114. package/templates/clean/pxlr-cms/packages/admin/src/components/editor/media-picker.tsx +202 -0
  115. package/templates/clean/pxlr-cms/packages/admin/src/components/editor/rich-text-editor.tsx +387 -0
  116. package/templates/clean/pxlr-cms/packages/admin/src/components/layout/auth-layout.tsx +43 -0
  117. package/templates/clean/pxlr-cms/packages/admin/src/components/layout/header.tsx +79 -0
  118. package/templates/clean/pxlr-cms/packages/admin/src/components/layout/sidebar.tsx +68 -0
  119. package/templates/clean/pxlr-cms/packages/admin/src/components/providers.tsx +29 -0
  120. package/templates/clean/pxlr-cms/packages/admin/src/components/schema-code-generator.tsx +326 -0
  121. package/templates/clean/pxlr-cms/packages/admin/src/components/ui/avatar.tsx +49 -0
  122. package/templates/clean/pxlr-cms/packages/admin/src/components/ui/button.tsx +55 -0
  123. package/templates/clean/pxlr-cms/packages/admin/src/components/ui/dropdown-menu.tsx +194 -0
  124. package/templates/clean/pxlr-cms/packages/admin/src/components/ui/input.tsx +24 -0
  125. package/templates/clean/pxlr-cms/packages/admin/src/components/ui/label.tsx +25 -0
  126. package/templates/clean/pxlr-cms/packages/admin/src/components/ui/toast.tsx +127 -0
  127. package/templates/clean/pxlr-cms/packages/admin/src/components/ui/toaster.tsx +35 -0
  128. package/templates/clean/pxlr-cms/packages/admin/src/components/ui/use-toast.ts +187 -0
  129. package/templates/clean/pxlr-cms/packages/admin/src/lib/api.ts +96 -0
  130. package/templates/clean/pxlr-cms/packages/admin/src/lib/i18n/context.tsx +60 -0
  131. package/templates/clean/pxlr-cms/packages/admin/src/lib/i18n/translations.ts +317 -0
  132. package/templates/clean/pxlr-cms/packages/admin/src/lib/store/auth.ts +51 -0
  133. package/templates/clean/pxlr-cms/packages/admin/src/lib/utils.ts +29 -0
  134. package/templates/clean/pxlr-cms/packages/admin/tailwind.config.ts +57 -0
  135. package/templates/clean/pxlr-cms/packages/admin/tsconfig.json +27 -0
  136. package/templates/clean/pxlr-cms/packages/api/.env.example +23 -0
  137. package/templates/clean/pxlr-cms/packages/api/Dockerfile +26 -0
  138. package/templates/clean/pxlr-cms/packages/api/package.json +42 -0
  139. package/templates/clean/pxlr-cms/packages/api/src/config.ts +39 -0
  140. package/templates/clean/pxlr-cms/packages/api/src/database/index.ts +60 -0
  141. package/templates/clean/pxlr-cms/packages/api/src/database/init.sql +178 -0
  142. package/templates/clean/pxlr-cms/packages/api/src/database/redis.ts +95 -0
  143. package/templates/clean/pxlr-cms/packages/api/src/index.ts +157 -0
  144. package/templates/clean/pxlr-cms/packages/api/src/modules/auth/routes.ts +256 -0
  145. package/templates/clean/pxlr-cms/packages/api/src/modules/content/routes.ts +385 -0
  146. package/templates/clean/pxlr-cms/packages/api/src/modules/media/routes.ts +312 -0
  147. package/templates/clean/pxlr-cms/packages/api/src/modules/realtime/handler.ts +228 -0
  148. package/templates/clean/pxlr-cms/packages/api/src/modules/schema/routes.ts +284 -0
  149. package/templates/clean/pxlr-cms/packages/api/src/modules/versions/routes.ts +70 -0
  150. package/templates/clean/pxlr-cms/packages/api/tsconfig.json +24 -0
  151. package/templates/clean/pxlr-cms/packages/shared/package.json +14 -0
  152. package/templates/clean/pxlr-cms/packages/shared/src/types/index.ts +139 -0
  153. package/templates/clean/pxlr-cms/packages/shared/tsconfig.json +18 -0
@@ -0,0 +1,188 @@
1
+ # PXLR CMS
2
+
3
+ Self-hosted Headless CMS inspired by Sanity. Full control over your content management with Docker deployment.
4
+
5
+ ## Features
6
+
7
+ - **Schema-driven content** - Define content types in code (TypeScript)
8
+ - **Rich text editing** - TipTap-based editor with full formatting support
9
+ - **Media library** - S3-compatible storage with image optimization
10
+ - **Content versioning** - Full version history with diff and rollback
11
+ - **Real-time collaboration** - WebSocket-based presence and updates
12
+ - **Multi-language support** - Built-in i18n for localized content
13
+ - **REST API** - Full CRUD API with Swagger documentation
14
+ - **Modern UI** - React/Next.js admin panel with dark mode
15
+
16
+ ## Quick Start
17
+
18
+ ### Prerequisites
19
+
20
+ - Docker & Docker Compose
21
+ - Node.js 20+ (for local development)
22
+
23
+ ### Start with Docker
24
+
25
+ ```bash
26
+ cd pxlr-cms
27
+
28
+ # Start all services
29
+ docker-compose up -d
30
+
31
+ # Wait for services to initialize (~30 seconds)
32
+ ```
33
+
34
+ ### Access
35
+
36
+ - **Admin Panel**: http://localhost:3000
37
+ - **API**: http://localhost:4000
38
+ - **API Docs**: http://localhost:4000/docs
39
+ - **MinIO Console**: http://localhost:9001
40
+
41
+ ### Default Credentials
42
+
43
+ - **Admin**: admin@pxlr.local / admin123
44
+ - **MinIO**: pxlr_minio / pxlr_minio_secret_2024
45
+
46
+ ## Architecture
47
+
48
+ ```
49
+ ┌─────────────────────────────────────────────────────┐
50
+ │ Docker Network │
51
+ ├─────────────────────────────────────────────────────┤
52
+ │ │
53
+ │ ┌─────────────┐ ┌─────────────┐ ┌──────────┐ │
54
+ │ │ Admin │ │ API │ │ MinIO │ │
55
+ │ │ (Next.js) │──▶│ (Fastify) │──▶│ (S3) │ │
56
+ │ │ :3000 │ │ :4000 │ │ :9000 │ │
57
+ │ └─────────────┘ └──────┬──────┘ └──────────┘ │
58
+ │ │ │
59
+ │ ┌──────▼──────┐ │
60
+ │ │ │ │
61
+ │ ┌─────┴─────┐ ┌─────┴─────┐ │
62
+ │ │ PostgreSQL│ │ Redis │ │
63
+ │ │ :5432 │ │ :6379 │ │
64
+ │ └───────────┘ └───────────┘ │
65
+ │ │
66
+ └─────────────────────────────────────────────────────┘
67
+ ```
68
+
69
+ ## Project Structure
70
+
71
+ ```
72
+ pxlr-cms/
73
+ ├── docker-compose.yml # Docker services configuration
74
+ ├── nginx/ # Nginx reverse proxy config
75
+ ├── packages/
76
+ │ ├── api/ # Backend API (Fastify + TypeScript)
77
+ │ │ ├── src/
78
+ │ │ │ ├── modules/ # API modules (auth, content, schema, media)
79
+ │ │ │ ├── database/ # Database connection and queries
80
+ │ │ │ └── index.ts # Entry point
81
+ │ │ └── Dockerfile
82
+ │ │
83
+ │ ├── admin/ # Admin Panel (Next.js)
84
+ │ │ ├── src/
85
+ │ │ │ ├── app/ # Next.js app router pages
86
+ │ │ │ ├── components/# React components
87
+ │ │ │ └── lib/ # Utilities and stores
88
+ │ │ └── Dockerfile
89
+ │ │
90
+ │ └── shared/ # Shared TypeScript types
91
+ │ └── src/types/
92
+ ```
93
+
94
+ ## API Endpoints
95
+
96
+ ### Authentication
97
+ - `POST /auth/login` - Login
98
+ - `POST /auth/register` - Register new user
99
+ - `GET /auth/me` - Get current user
100
+ - `POST /auth/logout` - Logout
101
+
102
+ ### Schemas
103
+ - `GET /schemas` - List all schemas
104
+ - `GET /schemas/:name` - Get schema by name
105
+ - `POST /schemas` - Create schema
106
+ - `PUT /schemas/:name` - Update schema
107
+ - `DELETE /schemas/:name` - Delete schema
108
+
109
+ ### Content
110
+ - `GET /content` - List documents (with filtering)
111
+ - `GET /content/:id` - Get document
112
+ - `POST /content` - Create document
113
+ - `PUT /content/:id` - Update document
114
+ - `DELETE /content/:id` - Delete document
115
+ - `GET /content/:id/versions` - Get version history
116
+ - `POST /content/:id/versions/:version/restore` - Restore version
117
+
118
+ ### Media
119
+ - `GET /media` - List media files
120
+ - `GET /media/:id` - Get file
121
+ - `POST /media/upload` - Upload file
122
+ - `PUT /media/:id` - Update metadata
123
+ - `DELETE /media/:id` - Delete file
124
+
125
+ ## Local Development
126
+
127
+ ### API Development
128
+
129
+ ```bash
130
+ cd packages/api
131
+ npm install
132
+ npm run dev
133
+ ```
134
+
135
+ ### Admin Development
136
+
137
+ ```bash
138
+ cd packages/admin
139
+ npm install
140
+ npm run dev
141
+ ```
142
+
143
+ ## Environment Variables
144
+
145
+ ### API (.env)
146
+ ```env
147
+ NODE_ENV=development
148
+ PORT=4000
149
+ DATABASE_URL=postgresql://pxlr:pxlr_secret_2024@localhost:5432/pxlr_cms
150
+ REDIS_URL=redis://localhost:6379
151
+ MINIO_ENDPOINT=localhost
152
+ MINIO_PORT=9000
153
+ MINIO_ACCESS_KEY=pxlr_minio
154
+ MINIO_SECRET_KEY=pxlr_minio_secret_2024
155
+ MINIO_BUCKET=pxlr-media
156
+ JWT_SECRET=your_jwt_secret_here
157
+ JWT_EXPIRES_IN=7d
158
+ ```
159
+
160
+ ### Admin (.env.local)
161
+ ```env
162
+ NEXT_PUBLIC_API_URL=http://localhost:4000
163
+ NEXT_PUBLIC_WS_URL=ws://localhost:4000
164
+ ```
165
+
166
+ ## Production Deployment
167
+
168
+ 1. Update environment variables with secure values
169
+ 2. Enable Nginx profile in docker-compose:
170
+ ```bash
171
+ docker-compose --profile production up -d
172
+ ```
173
+ 3. Configure SSL/TLS certificates
174
+ 4. Set up backups for PostgreSQL and MinIO
175
+
176
+ ## Technology Stack
177
+
178
+ - **Backend**: Node.js, Fastify, TypeScript
179
+ - **Frontend**: Next.js 15, React 19, TailwindCSS
180
+ - **Database**: PostgreSQL 16
181
+ - **Cache**: Redis 7
182
+ - **Storage**: MinIO (S3-compatible)
183
+ - **Editor**: TipTap
184
+ - **State**: Zustand, React Query
185
+
186
+ ## License
187
+
188
+ MIT License
@@ -0,0 +1,132 @@
1
+ services:
2
+ # PostgreSQL Database
3
+ postgres:
4
+ image: postgres:16-alpine
5
+ container_name: pxlr-postgres
6
+ restart: unless-stopped
7
+ environment:
8
+ POSTGRES_USER: pxlr
9
+ POSTGRES_PASSWORD: pxlr_secret_2024
10
+ POSTGRES_DB: pxlr_cms
11
+ volumes:
12
+ - postgres_data:/var/lib/postgresql/data
13
+ - ./packages/api/src/database/init.sql:/docker-entrypoint-initdb.d/init.sql
14
+ ports:
15
+ - "5432:5432"
16
+ healthcheck:
17
+ test: ["CMD-SHELL", "pg_isready -U pxlr -d pxlr_cms"]
18
+ interval: 10s
19
+ timeout: 5s
20
+ retries: 5
21
+
22
+ # Redis for caching and pub/sub
23
+ redis:
24
+ image: redis:7-alpine
25
+ container_name: pxlr-redis
26
+ restart: unless-stopped
27
+ command: redis-server --appendonly yes
28
+ volumes:
29
+ - redis_data:/data
30
+ ports:
31
+ - "6379:6379"
32
+ healthcheck:
33
+ test: ["CMD", "redis-cli", "ping"]
34
+ interval: 10s
35
+ timeout: 5s
36
+ retries: 5
37
+
38
+ # MinIO S3-compatible storage for media
39
+ minio:
40
+ image: minio/minio:latest
41
+ container_name: pxlr-minio
42
+ restart: unless-stopped
43
+ command: server /data --console-address ":9011"
44
+ environment:
45
+ MINIO_ROOT_USER: pxlr_minio
46
+ MINIO_ROOT_PASSWORD: pxlr_minio_secret_2024
47
+ volumes:
48
+ - minio_data:/data
49
+ ports:
50
+ - "9010:9000"
51
+ - "9011:9011"
52
+ healthcheck:
53
+ test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
54
+ interval: 30s
55
+ timeout: 20s
56
+ retries: 3
57
+
58
+ # Backend API
59
+ api:
60
+ build:
61
+ context: ./packages/api
62
+ dockerfile: Dockerfile
63
+ container_name: pxlr-api
64
+ restart: unless-stopped
65
+ environment:
66
+ NODE_ENV: development
67
+ PORT: 4000
68
+ DATABASE_URL: postgresql://pxlr:pxlr_secret_2024@postgres:5432/pxlr_cms
69
+ REDIS_URL: redis://redis:6379
70
+ MINIO_ENDPOINT: minio
71
+ MINIO_PORT: "9000"
72
+ MINIO_ACCESS_KEY: pxlr_minio
73
+ MINIO_SECRET_KEY: pxlr_minio_secret_2024
74
+ MINIO_BUCKET: pxlr-media
75
+ JWT_SECRET: pxlr_jwt_secret_change_in_production_2024
76
+ JWT_EXPIRES_IN: 7d
77
+ ports:
78
+ - "4000:4000"
79
+ depends_on:
80
+ postgres:
81
+ condition: service_healthy
82
+ redis:
83
+ condition: service_healthy
84
+ minio:
85
+ condition: service_healthy
86
+ volumes:
87
+ - ./packages/api:/app
88
+ - /app/node_modules
89
+
90
+ # Admin Panel
91
+ admin:
92
+ build:
93
+ context: ./packages/admin
94
+ dockerfile: Dockerfile
95
+ container_name: pxlr-admin
96
+ restart: unless-stopped
97
+ environment:
98
+ NODE_ENV: development
99
+ NEXT_PUBLIC_API_URL: http://localhost:4000
100
+ NEXT_PUBLIC_WS_URL: ws://localhost:4000
101
+ ports:
102
+ - "3333:3000"
103
+ depends_on:
104
+ - api
105
+ volumes:
106
+ - ./packages/admin:/app
107
+ - /app/node_modules
108
+ - /app/.next
109
+
110
+ # Nginx reverse proxy (for production)
111
+ nginx:
112
+ image: nginx:alpine
113
+ container_name: pxlr-nginx
114
+ restart: unless-stopped
115
+ ports:
116
+ - "80:80"
117
+ volumes:
118
+ - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
119
+ depends_on:
120
+ - api
121
+ - admin
122
+ profiles:
123
+ - production
124
+
125
+ volumes:
126
+ postgres_data:
127
+ redis_data:
128
+ minio_data:
129
+
130
+ networks:
131
+ default:
132
+ name: pxlr-network
@@ -0,0 +1,107 @@
1
+ events {
2
+ worker_connections 1024;
3
+ }
4
+
5
+ http {
6
+ include /etc/nginx/mime.types;
7
+ default_type application/octet-stream;
8
+
9
+ # Logging
10
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
11
+ '$status $body_bytes_sent "$http_referer" '
12
+ '"$http_user_agent" "$http_x_forwarded_for"';
13
+
14
+ access_log /var/log/nginx/access.log main;
15
+ error_log /var/log/nginx/error.log warn;
16
+
17
+ # Performance
18
+ sendfile on;
19
+ tcp_nopush on;
20
+ tcp_nodelay on;
21
+ keepalive_timeout 65;
22
+ types_hash_max_size 2048;
23
+
24
+ # Gzip compression
25
+ gzip on;
26
+ gzip_vary on;
27
+ gzip_proxied any;
28
+ gzip_comp_level 6;
29
+ gzip_types text/plain text/css text/xml application/json application/javascript
30
+ application/xml application/xml+rss text/javascript application/x-javascript;
31
+
32
+ # Rate limiting
33
+ limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
34
+
35
+ # Upstream servers
36
+ upstream api_backend {
37
+ server api:4000;
38
+ keepalive 32;
39
+ }
40
+
41
+ upstream admin_frontend {
42
+ server admin:3000;
43
+ keepalive 32;
44
+ }
45
+
46
+ server {
47
+ listen 80;
48
+ server_name localhost;
49
+
50
+ # Security headers
51
+ add_header X-Frame-Options "SAMEORIGIN" always;
52
+ add_header X-Content-Type-Options "nosniff" always;
53
+ add_header X-XSS-Protection "1; mode=block" always;
54
+ add_header Referrer-Policy "strict-origin-when-cross-origin" always;
55
+
56
+ # Max upload size
57
+ client_max_body_size 100M;
58
+
59
+ # API routes
60
+ location /api/ {
61
+ limit_req zone=api_limit burst=20 nodelay;
62
+
63
+ proxy_pass http://api_backend/;
64
+ proxy_http_version 1.1;
65
+ proxy_set_header Upgrade $http_upgrade;
66
+ proxy_set_header Connection "upgrade";
67
+ proxy_set_header Host $host;
68
+ proxy_set_header X-Real-IP $remote_addr;
69
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
70
+ proxy_set_header X-Forwarded-Proto $scheme;
71
+ proxy_cache_bypass $http_upgrade;
72
+ proxy_read_timeout 300s;
73
+ proxy_connect_timeout 75s;
74
+ }
75
+
76
+ # WebSocket for real-time
77
+ location /ws/ {
78
+ proxy_pass http://api_backend/ws/;
79
+ proxy_http_version 1.1;
80
+ proxy_set_header Upgrade $http_upgrade;
81
+ proxy_set_header Connection "upgrade";
82
+ proxy_set_header Host $host;
83
+ proxy_set_header X-Real-IP $remote_addr;
84
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
85
+ proxy_read_timeout 86400s;
86
+ }
87
+
88
+ # Admin panel (default)
89
+ location / {
90
+ proxy_pass http://admin_frontend;
91
+ proxy_http_version 1.1;
92
+ proxy_set_header Upgrade $http_upgrade;
93
+ proxy_set_header Connection "upgrade";
94
+ proxy_set_header Host $host;
95
+ proxy_set_header X-Real-IP $remote_addr;
96
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
97
+ proxy_set_header X-Forwarded-Proto $scheme;
98
+ }
99
+
100
+ # Health check endpoint
101
+ location /health {
102
+ access_log off;
103
+ return 200 "OK";
104
+ add_header Content-Type text/plain;
105
+ }
106
+ }
107
+ }
@@ -0,0 +1,4 @@
1
+ node_modules
2
+ .next
3
+ .git
4
+ *.log
@@ -0,0 +1,2 @@
1
+ NEXT_PUBLIC_API_URL=http://localhost:4000
2
+ NEXT_PUBLIC_WS_URL=ws://localhost:4000
@@ -0,0 +1,19 @@
1
+ # PXLR CMS Admin Panel Dockerfile
2
+ FROM node:20-alpine
3
+
4
+ WORKDIR /app
5
+
6
+ # Copy package files
7
+ COPY package.json ./
8
+
9
+ # Install dependencies
10
+ RUN npm cache clean --force && npm install --legacy-peer-deps
11
+
12
+ # Copy source code
13
+ COPY . .
14
+
15
+ # Expose port
16
+ EXPOSE 3000
17
+
18
+ # Start development server
19
+ CMD ["npm", "run", "dev"]
@@ -0,0 +1,6 @@
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+ /// <reference path="./.next/types/routes.d.ts" />
4
+
5
+ // NOTE: This file should not be edited
6
+ // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
@@ -0,0 +1,22 @@
1
+ import type { NextConfig } from 'next';
2
+
3
+ const nextConfig: NextConfig = {
4
+ devIndicators: false,
5
+ output: 'standalone',
6
+ images: {
7
+ remotePatterns: [
8
+ {
9
+ protocol: 'http',
10
+ hostname: 'localhost',
11
+ port: '9000',
12
+ },
13
+ {
14
+ protocol: 'http',
15
+ hostname: 'minio',
16
+ port: '9000',
17
+ },
18
+ ],
19
+ },
20
+ };
21
+
22
+ export default nextConfig;
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@pxlr/admin",
3
+ "version": "1.0.0",
4
+ "description": "PXLR CMS Admin Panel",
5
+ "private": true,
6
+ "scripts": {
7
+ "dev": "next dev",
8
+ "build": "next build",
9
+ "start": "next start",
10
+ "lint": "next lint"
11
+ },
12
+ "dependencies": {
13
+ "@hookform/resolvers": "^3.9.0",
14
+ "@radix-ui/react-alert-dialog": "^1.1.2",
15
+ "@radix-ui/react-avatar": "^1.1.1",
16
+ "@radix-ui/react-dialog": "^1.1.2",
17
+ "@radix-ui/react-dropdown-menu": "^2.1.2",
18
+ "@radix-ui/react-label": "^2.1.0",
19
+ "@radix-ui/react-select": "^2.1.2",
20
+ "@radix-ui/react-separator": "^1.1.0",
21
+ "@radix-ui/react-slot": "^1.1.0",
22
+ "@radix-ui/react-tabs": "^1.1.1",
23
+ "@radix-ui/react-toast": "^1.2.2",
24
+ "@radix-ui/react-tooltip": "^1.1.3",
25
+ "@tanstack/react-query": "^5.59.0",
26
+ "@tiptap/extension-color": "^2.10.0",
27
+ "@tiptap/extension-highlight": "^2.10.0",
28
+ "@tiptap/extension-image": "^2.10.0",
29
+ "@tiptap/extension-link": "^2.10.0",
30
+ "@tiptap/extension-placeholder": "^2.10.0",
31
+ "@tiptap/extension-text-align": "^2.10.0",
32
+ "@tiptap/extension-text-style": "^2.10.0",
33
+ "@tiptap/extension-underline": "^2.10.0",
34
+ "@tiptap/pm": "^2.10.0",
35
+ "@tiptap/react": "^2.10.0",
36
+ "@tiptap/starter-kit": "^2.10.0",
37
+ "class-variance-authority": "^0.7.0",
38
+ "clsx": "^2.1.1",
39
+ "date-fns": "^4.1.0",
40
+ "lucide-react": "^0.453.0",
41
+ "next": "^15.1.0",
42
+ "react": "^18.3.1",
43
+ "react-dom": "^18.3.1",
44
+ "react-dropzone": "^14.2.9",
45
+ "react-hook-form": "^7.53.0",
46
+ "socket.io-client": "^4.8.0",
47
+ "tailwind-merge": "^2.5.3",
48
+ "tailwindcss-animate": "^1.0.7",
49
+ "zod": "^3.23.8",
50
+ "zustand": "^5.0.0"
51
+ },
52
+ "devDependencies": {
53
+ "@types/node": "^22.0.0",
54
+ "@types/react": "^18.3.0",
55
+ "@types/react-dom": "^18.3.0",
56
+ "autoprefixer": "^10.4.20",
57
+ "eslint": "^9.0.0",
58
+ "eslint-config-next": "^15.1.0",
59
+ "postcss": "^8.4.47",
60
+ "tailwindcss": "^3.4.14",
61
+ "typescript": "^5.6.0"
62
+ }
63
+ }