@fnd-platform/cms 1.0.0-alpha.1
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.
- package/LICENSE +21 -0
- package/README.md +283 -0
- package/lib/cms-project.d.ts +127 -0
- package/lib/cms-project.d.ts.map +1 -0
- package/lib/cms-project.js +343 -0
- package/lib/cms-project.js.map +1 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +20 -0
- package/lib/index.js.map +1 -0
- package/lib/options.d.ts +59 -0
- package/lib/options.d.ts.map +1 -0
- package/lib/options.js +3 -0
- package/lib/options.js.map +1 -0
- package/lib/templates/admin-breadcrumbs.d.ts +13 -0
- package/lib/templates/admin-breadcrumbs.d.ts.map +1 -0
- package/lib/templates/admin-breadcrumbs.js +80 -0
- package/lib/templates/admin-breadcrumbs.js.map +1 -0
- package/lib/templates/admin-content-route.d.ts +18 -0
- package/lib/templates/admin-content-route.d.ts.map +1 -0
- package/lib/templates/admin-content-route.js +100 -0
- package/lib/templates/admin-content-route.js.map +1 -0
- package/lib/templates/admin-content-type-route.d.ts +9 -0
- package/lib/templates/admin-content-type-route.d.ts.map +1 -0
- package/lib/templates/admin-content-type-route.js +96 -0
- package/lib/templates/admin-content-type-route.js.map +1 -0
- package/lib/templates/admin-header.d.ts +13 -0
- package/lib/templates/admin-header.d.ts.map +1 -0
- package/lib/templates/admin-header.js +123 -0
- package/lib/templates/admin-header.js.map +1 -0
- package/lib/templates/admin-index.d.ts +9 -0
- package/lib/templates/admin-index.d.ts.map +1 -0
- package/lib/templates/admin-index.js +60 -0
- package/lib/templates/admin-index.js.map +1 -0
- package/lib/templates/admin-layout.d.ts +10 -0
- package/lib/templates/admin-layout.d.ts.map +1 -0
- package/lib/templates/admin-layout.js +46 -0
- package/lib/templates/admin-layout.js.map +1 -0
- package/lib/templates/admin-sidebar.d.ts +13 -0
- package/lib/templates/admin-sidebar.d.ts.map +1 -0
- package/lib/templates/admin-sidebar.js +149 -0
- package/lib/templates/admin-sidebar.js.map +1 -0
- package/lib/templates/content-editor.d.ts +10 -0
- package/lib/templates/content-editor.d.ts.map +1 -0
- package/lib/templates/content-editor.js +354 -0
- package/lib/templates/content-editor.js.map +1 -0
- package/lib/templates/content-schema.d.ts +10 -0
- package/lib/templates/content-schema.d.ts.map +1 -0
- package/lib/templates/content-schema.js +274 -0
- package/lib/templates/content-schema.js.map +1 -0
- package/lib/templates/content-table.d.ts +13 -0
- package/lib/templates/content-table.d.ts.map +1 -0
- package/lib/templates/content-table.js +177 -0
- package/lib/templates/content-table.js.map +1 -0
- package/lib/templates/content-types-examples.d.ts +19 -0
- package/lib/templates/content-types-examples.d.ts.map +1 -0
- package/lib/templates/content-types-examples.js +275 -0
- package/lib/templates/content-types-examples.js.map +1 -0
- package/lib/templates/content-types-registry.d.ts +10 -0
- package/lib/templates/content-types-registry.d.ts.map +1 -0
- package/lib/templates/content-types-registry.js +87 -0
- package/lib/templates/content-types-registry.js.map +1 -0
- package/lib/templates/content-types.d.ts +10 -0
- package/lib/templates/content-types.d.ts.map +1 -0
- package/lib/templates/content-types.js +384 -0
- package/lib/templates/content-types.js.map +1 -0
- package/lib/templates/dashboard-stats.d.ts +13 -0
- package/lib/templates/dashboard-stats.d.ts.map +1 -0
- package/lib/templates/dashboard-stats.js +117 -0
- package/lib/templates/dashboard-stats.js.map +1 -0
- package/lib/templates/editor/index.d.ts +6 -0
- package/lib/templates/editor/index.d.ts.map +1 -0
- package/lib/templates/editor/index.js +21 -0
- package/lib/templates/editor/index.js.map +1 -0
- package/lib/templates/editor/rich-text-editor.d.ts +7 -0
- package/lib/templates/editor/rich-text-editor.d.ts.map +1 -0
- package/lib/templates/editor/rich-text-editor.js +115 -0
- package/lib/templates/editor/rich-text-editor.js.map +1 -0
- package/lib/templates/editor/toolbar.d.ts +7 -0
- package/lib/templates/editor/toolbar.d.ts.map +1 -0
- package/lib/templates/editor/toolbar.js +272 -0
- package/lib/templates/editor/toolbar.js.map +1 -0
- package/lib/templates/form-fields/boolean-field.d.ts +7 -0
- package/lib/templates/form-fields/boolean-field.d.ts.map +1 -0
- package/lib/templates/form-fields/boolean-field.js +76 -0
- package/lib/templates/form-fields/boolean-field.js.map +1 -0
- package/lib/templates/form-fields/date-field.d.ts +7 -0
- package/lib/templates/form-fields/date-field.d.ts.map +1 -0
- package/lib/templates/form-fields/date-field.js +61 -0
- package/lib/templates/form-fields/date-field.js.map +1 -0
- package/lib/templates/form-fields/datetime-field.d.ts +7 -0
- package/lib/templates/form-fields/datetime-field.d.ts.map +1 -0
- package/lib/templates/form-fields/datetime-field.js +87 -0
- package/lib/templates/form-fields/datetime-field.js.map +1 -0
- package/lib/templates/form-fields/index.d.ts +23 -0
- package/lib/templates/form-fields/index.d.ts.map +1 -0
- package/lib/templates/form-fields/index.js +275 -0
- package/lib/templates/form-fields/index.js.map +1 -0
- package/lib/templates/form-fields/media-field.d.ts +10 -0
- package/lib/templates/form-fields/media-field.d.ts.map +1 -0
- package/lib/templates/form-fields/media-field.js +225 -0
- package/lib/templates/form-fields/media-field.js.map +1 -0
- package/lib/templates/form-fields/multiselect-field.d.ts +7 -0
- package/lib/templates/form-fields/multiselect-field.d.ts.map +1 -0
- package/lib/templates/form-fields/multiselect-field.js +121 -0
- package/lib/templates/form-fields/multiselect-field.js.map +1 -0
- package/lib/templates/form-fields/number-field.d.ts +7 -0
- package/lib/templates/form-fields/number-field.d.ts.map +1 -0
- package/lib/templates/form-fields/number-field.js +87 -0
- package/lib/templates/form-fields/number-field.js.map +1 -0
- package/lib/templates/form-fields/reference-field.d.ts +9 -0
- package/lib/templates/form-fields/reference-field.d.ts.map +1 -0
- package/lib/templates/form-fields/reference-field.js +145 -0
- package/lib/templates/form-fields/reference-field.js.map +1 -0
- package/lib/templates/form-fields/richtext-field.d.ts +9 -0
- package/lib/templates/form-fields/richtext-field.d.ts.map +1 -0
- package/lib/templates/form-fields/richtext-field.js +60 -0
- package/lib/templates/form-fields/richtext-field.js.map +1 -0
- package/lib/templates/form-fields/select-field.d.ts +7 -0
- package/lib/templates/form-fields/select-field.d.ts.map +1 -0
- package/lib/templates/form-fields/select-field.js +70 -0
- package/lib/templates/form-fields/select-field.js.map +1 -0
- package/lib/templates/form-fields/slug-field.d.ts +7 -0
- package/lib/templates/form-fields/slug-field.d.ts.map +1 -0
- package/lib/templates/form-fields/slug-field.js +143 -0
- package/lib/templates/form-fields/slug-field.js.map +1 -0
- package/lib/templates/form-fields/tags-field.d.ts +7 -0
- package/lib/templates/form-fields/tags-field.d.ts.map +1 -0
- package/lib/templates/form-fields/tags-field.js +172 -0
- package/lib/templates/form-fields/tags-field.js.map +1 -0
- package/lib/templates/form-fields/text-field.d.ts +7 -0
- package/lib/templates/form-fields/text-field.d.ts.map +1 -0
- package/lib/templates/form-fields/text-field.js +63 -0
- package/lib/templates/form-fields/text-field.js.map +1 -0
- package/lib/templates/form-fields/textarea-field.d.ts +7 -0
- package/lib/templates/form-fields/textarea-field.d.ts.map +1 -0
- package/lib/templates/form-fields/textarea-field.js +64 -0
- package/lib/templates/form-fields/textarea-field.js.map +1 -0
- package/lib/templates/index.d.ts +34 -0
- package/lib/templates/index.d.ts.map +1 -0
- package/lib/templates/index.js +92 -0
- package/lib/templates/index.js.map +1 -0
- package/lib/templates/media/index.d.ts +12 -0
- package/lib/templates/media/index.d.ts.map +1 -0
- package/lib/templates/media/index.js +50 -0
- package/lib/templates/media/index.js.map +1 -0
- package/lib/templates/media/media-api.d.ts +13 -0
- package/lib/templates/media/media-api.d.ts.map +1 -0
- package/lib/templates/media/media-api.js +274 -0
- package/lib/templates/media/media-api.js.map +1 -0
- package/lib/templates/media/media-grid.d.ts +14 -0
- package/lib/templates/media/media-grid.d.ts.map +1 -0
- package/lib/templates/media/media-grid.js +314 -0
- package/lib/templates/media/media-grid.js.map +1 -0
- package/lib/templates/media/media-library-route.d.ts +13 -0
- package/lib/templates/media/media-library-route.d.ts.map +1 -0
- package/lib/templates/media/media-library-route.js +105 -0
- package/lib/templates/media/media-library-route.js.map +1 -0
- package/lib/templates/media/media-picker.d.ts +13 -0
- package/lib/templates/media/media-picker.d.ts.map +1 -0
- package/lib/templates/media/media-picker.js +152 -0
- package/lib/templates/media/media-picker.js.map +1 -0
- package/lib/templates/media/media-uploader.d.ts +14 -0
- package/lib/templates/media/media-uploader.d.ts.map +1 -0
- package/lib/templates/media/media-uploader.js +318 -0
- package/lib/templates/media/media-uploader.js.map +1 -0
- package/lib/templates/recent-content.d.ts +13 -0
- package/lib/templates/recent-content.d.ts.map +1 -0
- package/lib/templates/recent-content.js +138 -0
- package/lib/templates/recent-content.js.map +1 -0
- package/lib/templates/slug-utils.d.ts +10 -0
- package/lib/templates/slug-utils.d.ts.map +1 -0
- package/lib/templates/slug-utils.js +194 -0
- package/lib/templates/slug-utils.js.map +1 -0
- package/lib/templates/ui-avatar.d.ts +8 -0
- package/lib/templates/ui-avatar.d.ts.map +1 -0
- package/lib/templates/ui-avatar.js +60 -0
- package/lib/templates/ui-avatar.js.map +1 -0
- package/lib/templates/ui-badge.d.ts +8 -0
- package/lib/templates/ui-badge.d.ts.map +1 -0
- package/lib/templates/ui-badge.js +52 -0
- package/lib/templates/ui-badge.js.map +1 -0
- package/lib/templates/ui-dialog.d.ts +10 -0
- package/lib/templates/ui-dialog.d.ts.map +1 -0
- package/lib/templates/ui-dialog.js +134 -0
- package/lib/templates/ui-dialog.js.map +1 -0
- package/lib/templates/ui-dropdown-menu.d.ts +8 -0
- package/lib/templates/ui-dropdown-menu.d.ts.map +1 -0
- package/lib/templates/ui-dropdown-menu.js +210 -0
- package/lib/templates/ui-dropdown-menu.js.map +1 -0
- package/lib/templates/ui-popover.d.ts +8 -0
- package/lib/templates/ui-popover.d.ts.map +1 -0
- package/lib/templates/ui-popover.js +43 -0
- package/lib/templates/ui-popover.js.map +1 -0
- package/lib/templates/ui-progress.d.ts +10 -0
- package/lib/templates/ui-progress.d.ts.map +1 -0
- package/lib/templates/ui-progress.js +40 -0
- package/lib/templates/ui-progress.js.map +1 -0
- package/lib/templates/ui-table.d.ts +8 -0
- package/lib/templates/ui-table.d.ts.map +1 -0
- package/lib/templates/ui-table.js +129 -0
- package/lib/templates/ui-table.js.map +1 -0
- package/lib/templates/ui-tabs.d.ts +10 -0
- package/lib/templates/ui-tabs.d.ts.map +1 -0
- package/lib/templates/ui-tabs.js +67 -0
- package/lib/templates/ui-tabs.js.map +1 -0
- package/package.json +52 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 fnd-platform contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# @fnd-platform/cms
|
|
2
|
+
|
|
3
|
+
Projen project class for generating headless CMS admin interfaces with Remix, shadcn/ui, content modeling, and media management in fnd-platform monorepos.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -D @fnd-platform/cms
|
|
9
|
+
# or
|
|
10
|
+
pnpm add -D @fnd-platform/cms
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
Add a CMS package to your monorepo in `.projenrc.ts`:
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { FndMonorepoProject } from '@fnd-platform/core';
|
|
19
|
+
import { FndApiProject } from '@fnd-platform/api';
|
|
20
|
+
import { FndCmsProject } from '@fnd-platform/cms';
|
|
21
|
+
|
|
22
|
+
const monorepo = new FndMonorepoProject({
|
|
23
|
+
name: 'my-app',
|
|
24
|
+
defaultReleaseBranch: 'main',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const api = new FndApiProject({
|
|
28
|
+
parent: monorepo,
|
|
29
|
+
name: 'api',
|
|
30
|
+
outdir: 'packages/api',
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const cms = new FndCmsProject({
|
|
34
|
+
parent: monorepo,
|
|
35
|
+
name: 'cms',
|
|
36
|
+
outdir: 'packages/cms',
|
|
37
|
+
api: api, // Link to API for content operations
|
|
38
|
+
port: 3001,
|
|
39
|
+
mediaUpload: true,
|
|
40
|
+
richTextEditor: 'tiptap',
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
monorepo.synth();
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Configuration Options
|
|
47
|
+
|
|
48
|
+
| Option | Type | Default | Description |
|
|
49
|
+
| ---------------- | ------------------------- | ----------------- | ---------------------------- |
|
|
50
|
+
| `parent` | `FndMonorepoProject` | **required** | Parent monorepo |
|
|
51
|
+
| `name` | `string` | **required** | Package name |
|
|
52
|
+
| `api` | `FndApiProject` | **required** | Linked API project |
|
|
53
|
+
| `outdir` | `string` | `packages/{name}` | Output directory |
|
|
54
|
+
| `port` | `number` | `3001` | Development server port |
|
|
55
|
+
| `mediaUpload` | `boolean` | `true` | Enable media upload features |
|
|
56
|
+
| `richTextEditor` | `'tiptap'` \| `'lexical'` | `'tiptap'` | Rich text editor library |
|
|
57
|
+
| `shadcnTheme` | `ShadcnTheme` | `'zinc'` | Theme color |
|
|
58
|
+
|
|
59
|
+
## What Gets Generated
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
packages/cms/
|
|
63
|
+
├── app/
|
|
64
|
+
│ ├── routes/
|
|
65
|
+
│ │ ├── _admin.tsx # Admin layout (protected)
|
|
66
|
+
│ │ ├── _admin._index.tsx # Dashboard
|
|
67
|
+
│ │ ├── _admin.content.tsx # Content list
|
|
68
|
+
│ │ ├── _admin.content.$type.tsx # Content by type
|
|
69
|
+
│ │ ├── _admin.content.$type.$id.tsx # Content editor
|
|
70
|
+
│ │ ├── _admin.content.$type.new.tsx # New content
|
|
71
|
+
│ │ ├── _admin.media.tsx # Media library
|
|
72
|
+
│ │ ├── _admin.settings.tsx # Settings
|
|
73
|
+
│ │ └── login.tsx # Admin login
|
|
74
|
+
│ ├── components/
|
|
75
|
+
│ │ ├── admin/ # Admin UI components
|
|
76
|
+
│ │ ├── editor/ # Rich text editor
|
|
77
|
+
│ │ └── ui/ # shadcn/ui components
|
|
78
|
+
│ ├── lib/
|
|
79
|
+
│ │ ├── api.server.ts # API client
|
|
80
|
+
│ │ ├── auth.server.ts # Auth utilities
|
|
81
|
+
│ │ └── content-types.ts # Content type definitions
|
|
82
|
+
│ └── content-types/ # Content type definitions
|
|
83
|
+
├── package.json
|
|
84
|
+
├── tailwind.config.js
|
|
85
|
+
├── vite.config.ts
|
|
86
|
+
└── tsconfig.json
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Features
|
|
90
|
+
|
|
91
|
+
- **Admin Interface** - Clean, modern admin UI built with shadcn/ui
|
|
92
|
+
- **Content Modeling** - Define flexible content types with various field types
|
|
93
|
+
- **Draft/Publish Workflow** - Content review and publishing workflow
|
|
94
|
+
- **Media Library** - Upload and manage images, videos, and files
|
|
95
|
+
- **Rich Text Editor** - Tiptap or Lexical-based content editing
|
|
96
|
+
- **Role-Based Access** - Admin, editor, and viewer roles
|
|
97
|
+
|
|
98
|
+
## Examples
|
|
99
|
+
|
|
100
|
+
### Content Type Definition
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// app/content-types/blog-post.ts
|
|
104
|
+
import { defineContentType } from '~/lib/content-types';
|
|
105
|
+
|
|
106
|
+
export const blogPost = defineContentType({
|
|
107
|
+
name: 'blog-post',
|
|
108
|
+
label: 'Blog Post',
|
|
109
|
+
icon: 'FileText',
|
|
110
|
+
|
|
111
|
+
fields: [
|
|
112
|
+
{
|
|
113
|
+
name: 'title',
|
|
114
|
+
type: 'text',
|
|
115
|
+
label: 'Title',
|
|
116
|
+
required: true,
|
|
117
|
+
maxLength: 200,
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: 'slug',
|
|
121
|
+
type: 'slug',
|
|
122
|
+
label: 'URL Slug',
|
|
123
|
+
required: true,
|
|
124
|
+
source: 'title',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: 'content',
|
|
128
|
+
type: 'richtext',
|
|
129
|
+
label: 'Content',
|
|
130
|
+
required: true,
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: 'featuredImage',
|
|
134
|
+
type: 'media',
|
|
135
|
+
label: 'Featured Image',
|
|
136
|
+
accept: ['image/*'],
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: 'publishedAt',
|
|
140
|
+
type: 'datetime',
|
|
141
|
+
label: 'Publish Date',
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Admin Dashboard Route
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
// app/routes/_admin._index.tsx
|
|
151
|
+
import { json, type LoaderFunctionArgs } from '@remix-run/node';
|
|
152
|
+
import { useLoaderData } from '@remix-run/react';
|
|
153
|
+
import { requireAdmin } from '~/lib/auth.server';
|
|
154
|
+
import { contentApi } from '~/lib/api.server';
|
|
155
|
+
|
|
156
|
+
export const loader = async ({ request }: LoaderFunctionArgs) => {
|
|
157
|
+
await requireAdmin(request);
|
|
158
|
+
|
|
159
|
+
const [stats, recentContent] = await Promise.all([
|
|
160
|
+
contentApi.getStats(),
|
|
161
|
+
contentApi.list({ limit: 10, sort: '-updatedAt' }),
|
|
162
|
+
]);
|
|
163
|
+
|
|
164
|
+
return json({ stats, recentContent });
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export default function Dashboard() {
|
|
168
|
+
const { stats, recentContent } = useLoaderData<typeof loader>();
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<div className="space-y-6">
|
|
172
|
+
<h1 className="text-2xl font-bold">Dashboard</h1>
|
|
173
|
+
{/* Dashboard content */}
|
|
174
|
+
</div>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Content Editor Route
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
// app/routes/_admin.content.$type.$id.tsx
|
|
183
|
+
import { json, redirect, type ActionFunctionArgs } from '@remix-run/node';
|
|
184
|
+
import { requireAdmin } from '~/lib/auth.server';
|
|
185
|
+
import { contentApi } from '~/lib/api.server';
|
|
186
|
+
|
|
187
|
+
export const action = async ({ request, params }: ActionFunctionArgs) => {
|
|
188
|
+
await requireAdmin(request);
|
|
189
|
+
|
|
190
|
+
const formData = await request.formData();
|
|
191
|
+
const intent = formData.get('intent');
|
|
192
|
+
|
|
193
|
+
if (intent === 'save') {
|
|
194
|
+
const data = Object.fromEntries(formData);
|
|
195
|
+
await contentApi.update(params.id!, data);
|
|
196
|
+
return json({ success: true });
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (intent === 'publish') {
|
|
200
|
+
await contentApi.publish(params.id!);
|
|
201
|
+
return json({ success: true });
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (intent === 'delete') {
|
|
205
|
+
await contentApi.delete(params.id!);
|
|
206
|
+
return redirect(`/admin/content/${params.type}`);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return json({ error: 'Invalid action' }, { status: 400 });
|
|
210
|
+
};
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Field Types
|
|
214
|
+
|
|
215
|
+
| Type | Description | Options |
|
|
216
|
+
| ----------- | ----------------- | ---------------------- |
|
|
217
|
+
| `text` | Single line text | `maxLength`, `pattern` |
|
|
218
|
+
| `textarea` | Multi-line text | `maxLength`, `rows` |
|
|
219
|
+
| `richtext` | Rich text editor | `toolbar`, `formats` |
|
|
220
|
+
| `number` | Numeric input | `min`, `max`, `step` |
|
|
221
|
+
| `boolean` | Toggle/checkbox | `default` |
|
|
222
|
+
| `select` | Dropdown select | `options` |
|
|
223
|
+
| `date` | Date picker | `min`, `max` |
|
|
224
|
+
| `datetime` | Date and time | `min`, `max` |
|
|
225
|
+
| `slug` | URL slug | `source` |
|
|
226
|
+
| `media` | Media picker | `accept`, `multiple` |
|
|
227
|
+
| `reference` | Content reference | `referenceType` |
|
|
228
|
+
| `tags` | Tag input | `suggestions` |
|
|
229
|
+
|
|
230
|
+
## Content Status
|
|
231
|
+
|
|
232
|
+
| Status | Description |
|
|
233
|
+
| ----------- | ------------------------ |
|
|
234
|
+
| `draft` | Being edited, not public |
|
|
235
|
+
| `published` | Live and visible |
|
|
236
|
+
| `scheduled` | Will publish at set time |
|
|
237
|
+
| `archived` | Hidden but preserved |
|
|
238
|
+
|
|
239
|
+
## Development
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
# Start development server
|
|
243
|
+
cd packages/cms
|
|
244
|
+
pnpm dev
|
|
245
|
+
|
|
246
|
+
# Build for production
|
|
247
|
+
pnpm build
|
|
248
|
+
|
|
249
|
+
# Run tests
|
|
250
|
+
pnpm test
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## API Reference
|
|
254
|
+
|
|
255
|
+
See the [full API documentation](../../docs/api/modules/cms_src.html) for detailed type definitions and examples.
|
|
256
|
+
|
|
257
|
+
### Project Class
|
|
258
|
+
|
|
259
|
+
- `FndCmsProject` - Projen project class for CMS packages
|
|
260
|
+
|
|
261
|
+
### Types
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
import type { FndCmsProjectOptions } from '@fnd-platform/cms';
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Requirements
|
|
268
|
+
|
|
269
|
+
- Node.js 20+
|
|
270
|
+
- pnpm 8+
|
|
271
|
+
- @fnd-platform/core
|
|
272
|
+
- @fnd-platform/api (for API linking)
|
|
273
|
+
|
|
274
|
+
## Related
|
|
275
|
+
|
|
276
|
+
- [@fnd-platform/core](../core/README.md) - Core Projen project classes
|
|
277
|
+
- [@fnd-platform/api](../api/README.md) - API package for backend
|
|
278
|
+
- [@fnd-platform/frontend](../frontend/README.md) - Public-facing frontend
|
|
279
|
+
- [@fnd-platform/cognito-auth](../cognito-auth/README.md) - Authentication
|
|
280
|
+
|
|
281
|
+
## License
|
|
282
|
+
|
|
283
|
+
MIT
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { FndFrontendProject } from '@fnd-platform/frontend';
|
|
2
|
+
import type { FndCmsProjectOptions } from './options';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a CMS admin package within an fnd-platform monorepo.
|
|
5
|
+
*
|
|
6
|
+
* This class generates a complete CMS admin interface scaffold with:
|
|
7
|
+
* - Remix app structure (inherited from FndFrontendProject)
|
|
8
|
+
* - Protected admin routes with authentication
|
|
9
|
+
* - Admin layout and dashboard
|
|
10
|
+
* - shadcn/ui components for admin UI
|
|
11
|
+
*
|
|
12
|
+
* The CMS extends the frontend project and adds admin-specific functionality.
|
|
13
|
+
* Authentication is always enabled for CMS (admin access required).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { FndMonorepoProject } from '@fnd-platform/core';
|
|
18
|
+
* import { FndApiProject } from '@fnd-platform/api';
|
|
19
|
+
* import { FndCmsProject } from '@fnd-platform/cms';
|
|
20
|
+
*
|
|
21
|
+
* const monorepo = new FndMonorepoProject({
|
|
22
|
+
* name: 'my-app',
|
|
23
|
+
* defaultReleaseBranch: 'main',
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* const api = new FndApiProject({
|
|
27
|
+
* parent: monorepo,
|
|
28
|
+
* name: 'api',
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* const cms = new FndCmsProject({
|
|
32
|
+
* parent: monorepo,
|
|
33
|
+
* name: 'cms',
|
|
34
|
+
* api: api,
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* monorepo.synth();
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare class FndCmsProject extends FndFrontendProject {
|
|
41
|
+
/**
|
|
42
|
+
* Whether media upload functionality is enabled.
|
|
43
|
+
*/
|
|
44
|
+
readonly mediaUpload: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Rich text editor to use for content editing.
|
|
47
|
+
*/
|
|
48
|
+
readonly richTextEditor: 'tiptap' | 'lexical';
|
|
49
|
+
/**
|
|
50
|
+
* Creates a new FndCmsProject.
|
|
51
|
+
*
|
|
52
|
+
* @param options - Configuration options for the CMS project
|
|
53
|
+
* @throws {Error} If required options are missing
|
|
54
|
+
*/
|
|
55
|
+
constructor(options: FndCmsProjectOptions);
|
|
56
|
+
/**
|
|
57
|
+
* Generates additional shadcn/ui components for the CMS.
|
|
58
|
+
*
|
|
59
|
+
* Creates:
|
|
60
|
+
* - badge.tsx - Status badge component
|
|
61
|
+
* - avatar.tsx - User avatar component
|
|
62
|
+
* - dropdown-menu.tsx - Dropdown menu component
|
|
63
|
+
* - table.tsx - Table component
|
|
64
|
+
* - popover.tsx - Popover component for link dialogs
|
|
65
|
+
*/
|
|
66
|
+
private generateUiComponents;
|
|
67
|
+
/**
|
|
68
|
+
* Generates the admin components for the CMS.
|
|
69
|
+
*
|
|
70
|
+
* Creates:
|
|
71
|
+
* - sidebar.tsx - Admin sidebar navigation
|
|
72
|
+
* - header.tsx - Admin header with user menu
|
|
73
|
+
* - breadcrumbs.tsx - Breadcrumb navigation
|
|
74
|
+
* - dashboard-stats.tsx - Dashboard statistics cards
|
|
75
|
+
* - recent-content.tsx - Recent content list
|
|
76
|
+
* - content-table.tsx - Content list table
|
|
77
|
+
*/
|
|
78
|
+
private generateAdminComponents;
|
|
79
|
+
/**
|
|
80
|
+
* Generates the admin routes for the CMS.
|
|
81
|
+
*
|
|
82
|
+
* Creates:
|
|
83
|
+
* - _admin.tsx - Admin layout with sidebar and header
|
|
84
|
+
* - _admin._index.tsx - Admin dashboard with stats
|
|
85
|
+
* - _admin.content.tsx - Content section layout
|
|
86
|
+
* - _admin.content._index.tsx - Content overview
|
|
87
|
+
* - _admin.content.$type.tsx - Content type list
|
|
88
|
+
*/
|
|
89
|
+
private generateAdminRoutes;
|
|
90
|
+
/**
|
|
91
|
+
* Generates the content type definition system.
|
|
92
|
+
*
|
|
93
|
+
* Creates:
|
|
94
|
+
* - app/lib/content-types.ts - Content type definitions and interfaces
|
|
95
|
+
* - app/lib/content-schema.ts - Zod schema generation utilities
|
|
96
|
+
* - app/lib/slug-utils.ts - Slug generation utilities
|
|
97
|
+
* - app/content-types/index.ts - Content type registry
|
|
98
|
+
* - app/content-types/blog-post.ts - Example blog post content type
|
|
99
|
+
* - app/content-types/page.ts - Example page content type
|
|
100
|
+
* - app/components/form-fields/* - All form field components
|
|
101
|
+
* - app/components/admin/content-editor.tsx - Dynamic content editor
|
|
102
|
+
*/
|
|
103
|
+
private generateContentTypeSystem;
|
|
104
|
+
/**
|
|
105
|
+
* Generates the editor components for rich text editing.
|
|
106
|
+
*
|
|
107
|
+
* Creates:
|
|
108
|
+
* - app/components/editor/toolbar.tsx - Editor toolbar with formatting buttons
|
|
109
|
+
* - app/components/editor/rich-text-editor.tsx - Tiptap-based rich text editor
|
|
110
|
+
*/
|
|
111
|
+
private generateEditorComponents;
|
|
112
|
+
/**
|
|
113
|
+
* Generates the media library components.
|
|
114
|
+
*
|
|
115
|
+
* Creates:
|
|
116
|
+
* - app/lib/media-api.ts - Client-side API helpers for presigned URL uploads
|
|
117
|
+
* - app/components/media/media-uploader.tsx - Drag-drop upload with progress
|
|
118
|
+
* - app/components/media/media-grid.tsx - Grid display with selection
|
|
119
|
+
* - app/components/media/media-picker.tsx - Dialog for field integration
|
|
120
|
+
* - app/routes/_admin.media.tsx - Media library route
|
|
121
|
+
* - app/components/ui/progress.tsx - Progress bar component
|
|
122
|
+
* - app/components/ui/dialog.tsx - Dialog component
|
|
123
|
+
* - app/components/ui/tabs.tsx - Tabs component
|
|
124
|
+
*/
|
|
125
|
+
private generateMediaComponents;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=cms-project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cms-project.d.ts","sourceRoot":"","sources":["../src/cms-project.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAwDtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,qBAAa,aAAc,SAAQ,kBAAkB;IACnD;;OAEG;IACH,SAAgB,WAAW,EAAE,OAAO,CAAC;IAErC;;OAEG;IACH,SAAgB,cAAc,EAAE,QAAQ,GAAG,SAAS,CAAC;IAErD;;;;;OAKG;gBACS,OAAO,EAAE,oBAAoB;IA6DzC;;;;;;;;;OASG;IACH,OAAO,CAAC,oBAAoB;IAsB5B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,uBAAuB;IA0B/B;;;;;;;;;OASG;IACH,OAAO,CAAC,mBAAmB;IA2B3B;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,yBAAyB;IA0FjC;;;;;;OAMG;IACH,OAAO,CAAC,wBAAwB;IAUhC;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,uBAAuB;CAqChC"}
|