plum-cms 0.1.2 → 0.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/README.md +66 -3
- data/app/assets/builds/tailwind.css +1 -1
- data/app/assets/stylesheets/plum/control_panel.css +1 -1
- data/app/assets/tailwind/application.css +42 -0
- data/app/controllers/plum/api/v1/entries_controller.rb +48 -0
- data/app/controllers/plum/cp/assets_controller.rb +4 -1
- data/app/controllers/plum/cp/content_types_controller.rb +25 -2
- data/app/controllers/plum/cp/entries_controller.rb +119 -9
- data/app/controllers/plum/cp/entry_revisions_controller.rb +27 -0
- data/app/controllers/plum/cp/fieldsets_controller.rb +37 -0
- data/app/controllers/plum/cp/site_settings_controller.rb +20 -1
- data/app/controllers/plum/pages_controller.rb +26 -1
- data/app/javascript/controllers/plum/asset_collection_controller.js +18 -0
- data/app/javascript/controllers/plum/blueprint_controller.js +202 -25
- data/app/javascript/controllers/plum/conditional_fields_controller.js +43 -0
- data/app/javascript/controllers/plum/focal_point_controller.js +16 -0
- data/app/javascript/controllers/plum/structured_field_controller.js +133 -0
- data/app/models/plum/asset.rb +5 -1
- data/app/models/plum/content_type.rb +63 -1
- data/app/models/plum/entry.rb +225 -1
- data/app/models/plum/entry_revision.rb +14 -0
- data/app/models/plum/fieldset.rb +17 -0
- data/app/models/plum/site.rb +15 -0
- data/app/models/plum/user.rb +1 -0
- data/app/services/plum/entry_serializer.rb +36 -0
- data/app/services/plum/field_expander.rb +12 -1
- data/app/services/plum/field_options.rb +21 -0
- data/app/services/plum/field_type_registry.rb +88 -0
- data/app/services/plum/liquid_context.rb +7 -1
- data/app/views/layouts/plum/cp.html.erb +2 -0
- data/app/views/plum/cp/assets/_form.html.erb +13 -1
- data/app/views/plum/cp/content_types/_form.html.erb +81 -24
- data/app/views/plum/cp/custom_fields/_input.html.erb +5 -0
- data/app/views/plum/cp/entries/_form.html.erb +108 -31
- data/app/views/plum/cp/entries/edit.html.erb +16 -0
- data/app/views/plum/cp/entry_revisions/index.html.erb +25 -0
- data/app/views/plum/cp/fieldsets/index.html.erb +30 -0
- data/app/views/plum/cp/site_settings/edit.html.erb +12 -0
- data/config/plum_routes.rb +15 -0
- data/db/engine_migrate/20260807130000_create_plum_entry_revisions.rb +16 -0
- data/db/engine_migrate/20260807140000_create_plum_fieldsets.rb +13 -0
- data/db/engine_migrate/20260807150000_add_focal_point_to_plum_assets.rb +6 -0
- data/db/engine_migrate/20260807160000_add_localization_to_plum_entries.rb +9 -0
- data/docs/blueprint-fields.md +55 -0
- data/docs/extensions.md +32 -0
- data/docs/product-principles.md +73 -0
- data/docs/roadmap.md +98 -0
- data/docs/site/homepage.md +104 -0
- data/docs/site/information-architecture.md +176 -0
- data/docs/statamic-parity.md +28 -0
- data/docs/vision.md +82 -0
- data/lib/plum/version.rb +1 -1
- data/lib/plum.rb +4 -0
- data/lib/tasks/plum_styles.rake +12 -0
- metadata +31 -6
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Blueprint fields
|
|
2
|
+
|
|
3
|
+
Plum stores a content type blueprint as JSON with a `fields` array. Field
|
|
4
|
+
handles are stable template and storage keys: lowercase letters, numbers, and
|
|
5
|
+
underscores, beginning with a letter.
|
|
6
|
+
|
|
7
|
+
## Shared configuration
|
|
8
|
+
|
|
9
|
+
Every data field accepts `handle`, `type`, `label`, `instructions`, `required`,
|
|
10
|
+
`default`, `placeholder`, and `width`. Width is a grid span from 1 through 12.
|
|
11
|
+
A `section` organizes the entry form but stores no value.
|
|
12
|
+
|
|
13
|
+
`condition` controls visibility using another field:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{ "field": "format", "operator": "equals", "value": "feature" }
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Operators: `equals`, `not_equals`, `contains`, `empty`, and `not_empty`.
|
|
20
|
+
|
|
21
|
+
## Type-specific configuration
|
|
22
|
+
|
|
23
|
+
| Type | Configuration | Stored value |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| `text`, `textarea`, `rich_text`, `url`, `color` | Shared options | String |
|
|
26
|
+
| `number` | `number_kind`, `min`, `max`, `step`, `unit` | Number |
|
|
27
|
+
| `boolean` | Shared options | Boolean |
|
|
28
|
+
| `date` | `date_mode`, `min`, `max` | ISO date/time string |
|
|
29
|
+
| `select`, `radio`, `button_group` | `options` | Option value |
|
|
30
|
+
| `checkboxes` | `options` | Option-value array |
|
|
31
|
+
| `taxonomy` | `taxonomy` | Entry-term associations |
|
|
32
|
+
| `image` | Optional `folder` | Asset ID |
|
|
33
|
+
| `images` | `min_items`, `max_items` | Asset-ID array |
|
|
34
|
+
| `relationship` | `content_type`, `multiple`, item limits | Entry ID or ID array |
|
|
35
|
+
| `blocks` | Optional `blocks` allowlist | Block array |
|
|
36
|
+
| `list` | `min_items`, `max_items`, `unique` | String array |
|
|
37
|
+
| `group` | Nested `fields` | Object |
|
|
38
|
+
| `repeater` | Nested `fields`, item limits | Object array |
|
|
39
|
+
| `section` | Shared presentation options | Nothing |
|
|
40
|
+
|
|
41
|
+
Options may be strings or `{ "label": "Human label", "value": "stable_value" }`
|
|
42
|
+
objects. Existing string options remain supported.
|
|
43
|
+
|
|
44
|
+
## Theme values
|
|
45
|
+
|
|
46
|
+
Liquid receives expanded assets and relationships. An `image` becomes an asset
|
|
47
|
+
object, `images` becomes an array of asset objects, and relationships become an
|
|
48
|
+
entry object or ordered array. Stored IDs remain internal to the editor.
|
|
49
|
+
|
|
50
|
+
## Compatibility policy
|
|
51
|
+
|
|
52
|
+
Blueprint additions are backward compatible. Plum continues to read legacy
|
|
53
|
+
string options and single-value relationship/image fields. Changing a field's
|
|
54
|
+
type or handle is a content migration and should be performed in application
|
|
55
|
+
code before deploying the new blueprint.
|
data/docs/extensions.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Extending Plum
|
|
2
|
+
|
|
3
|
+
Plum exposes Rails-native extension points for host applications and gems. An
|
|
4
|
+
initializer can register a field type with its control-panel partial and value
|
|
5
|
+
pipeline:
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
Plum.register_field_type(
|
|
9
|
+
handle: :postal_code,
|
|
10
|
+
label: "Postal Code",
|
|
11
|
+
partial: "my_engine/fields/postal_code",
|
|
12
|
+
normalizer: ->(value:, **) { value.to_s.upcase.delete(" ") },
|
|
13
|
+
validator: ->(value:, **) { "is invalid" unless value.to_s.match?(/\A\d{5}\z/) },
|
|
14
|
+
expander: ->(value:, **) { { "value" => value, "country" => "US" } }
|
|
15
|
+
)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The partial receives `field`, `field_handle`, `field_id`, `field_value`, and
|
|
19
|
+
`entry`. Its submitted input must use `entry[data][HANDLE]`.
|
|
20
|
+
|
|
21
|
+
The normalizer runs before persistence and receives `value`, `field`, `entry`,
|
|
22
|
+
and `controller`. The validator runs on the normalized entry value and returns
|
|
23
|
+
one message, multiple messages, or `nil`. The expander controls the value sent
|
|
24
|
+
to Liquid and the JSON content API and receives `value`, `field`, `site`, and
|
|
25
|
+
`expander`.
|
|
26
|
+
|
|
27
|
+
Registration rejects invalid or duplicate handles. Custom types automatically
|
|
28
|
+
appear in the visual blueprint type picker and participate in normal required,
|
|
29
|
+
default, instruction, conditional-visibility, and field-width behavior.
|
|
30
|
+
|
|
31
|
+
Plum also supports registered content sources and host-owned authorization; see
|
|
32
|
+
the corresponding README sections for those APIs.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Product Principles
|
|
2
|
+
|
|
3
|
+
These principles guide product and architectural decisions in Plum.
|
|
4
|
+
|
|
5
|
+
## Rails Owns the Application
|
|
6
|
+
|
|
7
|
+
The host application has the final say. Plum should integrate with its users,
|
|
8
|
+
authorization, tenancy, models, jobs, mail, storage, routes, and deployment
|
|
9
|
+
instead of creating parallel systems.
|
|
10
|
+
|
|
11
|
+
## The First Useful Result Is Fast
|
|
12
|
+
|
|
13
|
+
Installation must lead to an editable, published page in less than ten minutes.
|
|
14
|
+
Defaults should be good enough to ship and understandable enough to replace.
|
|
15
|
+
|
|
16
|
+
## The Escape Hatches Are Ruby
|
|
17
|
+
|
|
18
|
+
When a project exceeds Plum's conventions, developers should extend it with
|
|
19
|
+
ordinary Ruby, Rails configuration, models, controllers, helpers, and views.
|
|
20
|
+
Plum should not require a proprietary plugin runtime.
|
|
21
|
+
|
|
22
|
+
## Editors Do Not Need to Know Rails
|
|
23
|
+
|
|
24
|
+
Developers define content structure and presentation. Editors should receive a
|
|
25
|
+
clear, forgiving interface with preview, validation, history, and recovery.
|
|
26
|
+
|
|
27
|
+
## Content Is Structured and Portable
|
|
28
|
+
|
|
29
|
+
Content should be reusable across templates and exportable with its schema and
|
|
30
|
+
assets. A site owner must be able to leave without scraping rendered HTML or
|
|
31
|
+
depending on a Plum service.
|
|
32
|
+
|
|
33
|
+
## One Stack Is a Feature
|
|
34
|
+
|
|
35
|
+
Plum should not require Node services, a remote CMS database, webhooks, API
|
|
36
|
+
tokens, or a separate frontend. Optional integrations may add capability, but
|
|
37
|
+
the complete product must work as a conventional Rails application.
|
|
38
|
+
|
|
39
|
+
## SQLite Is a First-Class Production Path
|
|
40
|
+
|
|
41
|
+
Small content sites should run reliably with SQLite and persistent storage.
|
|
42
|
+
Plum must also remain database-agnostic for embedded and higher-scale uses.
|
|
43
|
+
|
|
44
|
+
## Sites Are Operationally Independent
|
|
45
|
+
|
|
46
|
+
For agency work, one client site should be one portable application, container,
|
|
47
|
+
database, and backup unit. For SaaS products, site scoping should support many
|
|
48
|
+
tenants inside one host application. Plum should document both patterns rather
|
|
49
|
+
than forcing one onto the other.
|
|
50
|
+
|
|
51
|
+
## Deployment Tools Have Clear Boundaries
|
|
52
|
+
|
|
53
|
+
Plum creates and manages content applications. A Plum CLI may scaffold, inspect,
|
|
54
|
+
export, import, upgrade, and package them. ONCE, Kamal, and other deployment
|
|
55
|
+
tools operate the resulting containers and servers. Plum should integrate
|
|
56
|
+
cleanly without becoming an infrastructure orchestrator.
|
|
57
|
+
|
|
58
|
+
## Documentation Is Part of the Product
|
|
59
|
+
|
|
60
|
+
Every public capability needs an example and a clear contract. If a feature is
|
|
61
|
+
difficult to explain, its design is not finished.
|
|
62
|
+
|
|
63
|
+
## Dogfood Without Special Cases
|
|
64
|
+
|
|
65
|
+
The Plum marketing and documentation site must run on the public product. Any
|
|
66
|
+
general improvement it needs belongs in Plum; site-specific behavior belongs in
|
|
67
|
+
the site's application or theme.
|
|
68
|
+
|
|
69
|
+
## Prefer Coherence Over Feature Count
|
|
70
|
+
|
|
71
|
+
Plum should excel at the everyday path from modeling content to publishing a
|
|
72
|
+
site. Features that strengthen installation, authoring confidence, portability,
|
|
73
|
+
and Rails integration take priority over breadth for its own sake.
|
data/docs/roadmap.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
Plum's roadmap is organized by outcomes rather than promised dates. Items move
|
|
4
|
+
as the product is exercised in real applications and the Rails community gives
|
|
5
|
+
feedback.
|
|
6
|
+
|
|
7
|
+
## Now: Make Plum Real and Adoptable
|
|
8
|
+
|
|
9
|
+
The current milestone is to build and publish the Plum marketing and
|
|
10
|
+
documentation site as a standalone Rails application powered by Plum and
|
|
11
|
+
SQLite.
|
|
12
|
+
|
|
13
|
+
### Product foundation
|
|
14
|
+
|
|
15
|
+
- Publish a clear vision, product principles, and supported use cases.
|
|
16
|
+
- Build `plumcms.org` with Plum as an external dependency.
|
|
17
|
+
- Define a portable production layout for the SQLite database, uploaded assets,
|
|
18
|
+
and mutable site data.
|
|
19
|
+
- Package the site as an ONCE-compatible Docker application.
|
|
20
|
+
- Exercise installation, initialization, health checks, upgrades, backup, and
|
|
21
|
+
restore on a real VM.
|
|
22
|
+
- Keep SQLite and PostgreSQL verification in CI.
|
|
23
|
+
|
|
24
|
+
### Documentation
|
|
25
|
+
|
|
26
|
+
- Document installation and the first editable page.
|
|
27
|
+
- Document sites, content types, fields, entries, and publishing.
|
|
28
|
+
- Document blocks, assets, relationships, taxonomies, navigation, globals, and
|
|
29
|
+
forms.
|
|
30
|
+
- Document Liquid themes and host content sources.
|
|
31
|
+
- Document embedded authentication, authorization, tenancy, and routing.
|
|
32
|
+
- Document standalone SQLite and embedded PostgreSQL deployments.
|
|
33
|
+
- Publish configuration, troubleshooting, and upgrade references.
|
|
34
|
+
|
|
35
|
+
### Distribution
|
|
36
|
+
|
|
37
|
+
- Publish the `plum` gem.
|
|
38
|
+
- State supported Ruby and Rails versions.
|
|
39
|
+
- Establish semantic versioning and an upgrade policy.
|
|
40
|
+
- Test fresh external installations and upgrades in CI.
|
|
41
|
+
- Provide a production-ready container contract and example application.
|
|
42
|
+
|
|
43
|
+
## Next: Editorial Confidence and Portability
|
|
44
|
+
|
|
45
|
+
Once the public site proves the basic workflow, focus on the features editors
|
|
46
|
+
and agencies need to trust Plum in production.
|
|
47
|
+
|
|
48
|
+
- Draft preview.
|
|
49
|
+
- Revisions and rollback.
|
|
50
|
+
- Scheduled publishing.
|
|
51
|
+
- Multi-entry relationships.
|
|
52
|
+
- Reusable blocks and sections.
|
|
53
|
+
- Content, schema, and asset export/import.
|
|
54
|
+
- Document hierarchy, tables of contents, and site search.
|
|
55
|
+
- SEO metadata, canonical URLs, sitemaps, feeds, and redirect management.
|
|
56
|
+
- Stronger asset organization and image editing.
|
|
57
|
+
- Form spam protection and improved submission workflows.
|
|
58
|
+
- Tested backup and restore commands.
|
|
59
|
+
|
|
60
|
+
## Later: The Rails Content Ecosystem
|
|
61
|
+
|
|
62
|
+
After installation and production operation are dependable, make Plum easier to
|
|
63
|
+
adopt repeatedly and extend publicly.
|
|
64
|
+
|
|
65
|
+
- A thin `plum` CLI for new sites, diagnostics, themes, export/import, upgrades,
|
|
66
|
+
and packaging.
|
|
67
|
+
- Starter applications for common content-site use cases.
|
|
68
|
+
- A documented extension contract for fields, blocks, and content sources.
|
|
69
|
+
- A collection of high-quality open themes and blocks.
|
|
70
|
+
- Theme scaffolding, validation, packaging, and distribution tools.
|
|
71
|
+
- Importers for common CMS and structured-data formats.
|
|
72
|
+
- Optional content APIs for applications that genuinely need them.
|
|
73
|
+
- Community examples, case studies, talks, and contribution programs.
|
|
74
|
+
|
|
75
|
+
## Plum 1.0
|
|
76
|
+
|
|
77
|
+
Plum 1.0 means another Rails developer can reproduce what powers
|
|
78
|
+
`plumcms.org` without private knowledge or site-specific patches.
|
|
79
|
+
|
|
80
|
+
It requires:
|
|
81
|
+
|
|
82
|
+
- a published, versioned gem;
|
|
83
|
+
- an editable page within ten minutes of installation;
|
|
84
|
+
- dependable standalone and embedded installation paths;
|
|
85
|
+
- a documented SQLite production deployment;
|
|
86
|
+
- clean host authentication, authorization, and tenancy integration;
|
|
87
|
+
- preview, revisions, export, backup, and restore;
|
|
88
|
+
- complete documentation for the supported public surface;
|
|
89
|
+
- a tested upgrade path;
|
|
90
|
+
- at least one production standalone site and one production embedded use; and
|
|
91
|
+
- a public example application that agencies can study and adapt.
|
|
92
|
+
|
|
93
|
+
## Not on the Near-Term Roadmap
|
|
94
|
+
|
|
95
|
+
Plum is not currently trying to become a general-purpose admin framework, a
|
|
96
|
+
freeform visual design tool, an ecommerce platform, or a hosted headless CMS.
|
|
97
|
+
Those products solve different problems. Plum's focus is managed content that
|
|
98
|
+
belongs inside Rails.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Homepage Copy
|
|
2
|
+
|
|
3
|
+
## Hero
|
|
4
|
+
|
|
5
|
+
### Plum
|
|
6
|
+
|
|
7
|
+
**The Rails-native CMS.**
|
|
8
|
+
|
|
9
|
+
Add managed content to an existing Rails application or build a complete
|
|
10
|
+
content-first site—without leaving the Rails stack.
|
|
11
|
+
|
|
12
|
+
Primary action: **Get started**
|
|
13
|
+
|
|
14
|
+
Secondary action: **View on GitHub**
|
|
15
|
+
|
|
16
|
+
Supporting note: Open source. Self-hosted. SQLite and PostgreSQL.
|
|
17
|
+
|
|
18
|
+
## One Stack, Complete Control
|
|
19
|
+
|
|
20
|
+
Plum uses the Rails application you already understand: its database, users,
|
|
21
|
+
authorization, jobs, mail, storage, and deployment. There is no external CMS to
|
|
22
|
+
synchronize and no second frontend to maintain.
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
gem "plum"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
bin/rails generate plum:install --mount-path=/website
|
|
30
|
+
bin/rails db:migrate
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Two Ways to Use Plum
|
|
34
|
+
|
|
35
|
+
### Add content to your application
|
|
36
|
+
|
|
37
|
+
Mount Plum in an existing Rails product. Let customers or editors manage pages,
|
|
38
|
+
navigation, documentation, announcements, and structured content while the host
|
|
39
|
+
application continues to own identity and business data.
|
|
40
|
+
|
|
41
|
+
Action: **Embed Plum**
|
|
42
|
+
|
|
43
|
+
### Build the whole site with Plum
|
|
44
|
+
|
|
45
|
+
Start with Rails, SQLite, and a Plum theme. Ship a fast, portable content site
|
|
46
|
+
that can grow into a custom Rails application whenever the project demands it.
|
|
47
|
+
|
|
48
|
+
Action: **Build a Plum site**
|
|
49
|
+
|
|
50
|
+
## Application Data Meets Editorial Content
|
|
51
|
+
|
|
52
|
+
Expose host application data safely to Plum templates without copying it into a
|
|
53
|
+
remote CMS.
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
Plum.configure do |config|
|
|
57
|
+
config.current_site_resolver = ->(_) { Current.account.plum_site }
|
|
58
|
+
config.current_user_resolver = ->(_) { Current.user }
|
|
59
|
+
|
|
60
|
+
config.register_content_source :products do |context|
|
|
61
|
+
context.owner.products.published
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Editors manage the story. Rails remains the source of truth for the application.
|
|
67
|
+
|
|
68
|
+
## Familiar Rails Foundations
|
|
69
|
+
|
|
70
|
+
- Rails 8 engine
|
|
71
|
+
- Hotwire control panel
|
|
72
|
+
- Active Record content
|
|
73
|
+
- Active Storage assets
|
|
74
|
+
- Active Job notifications
|
|
75
|
+
- Liquid themes
|
|
76
|
+
- SQLite and PostgreSQL
|
|
77
|
+
- Host-owned authentication and authorization
|
|
78
|
+
|
|
79
|
+
## For Independent Developers and Agencies
|
|
80
|
+
|
|
81
|
+
Package each client site as an independent Rails application with its own
|
|
82
|
+
SQLite database, assets, domain, and backup. Run several sites economically on
|
|
83
|
+
one VM with an ONCE-compatible container, and move any client without untangling
|
|
84
|
+
a shared CMS installation.
|
|
85
|
+
|
|
86
|
+
Action: **See the agency model**
|
|
87
|
+
|
|
88
|
+
## Built in Public, Used for Real
|
|
89
|
+
|
|
90
|
+
This website is a Rails application powered by Plum and SQLite. The same public
|
|
91
|
+
engine, theme system, and deployment path are available to every Plum project.
|
|
92
|
+
|
|
93
|
+
Action: **How this site works**
|
|
94
|
+
|
|
95
|
+
## Closing Call to Action
|
|
96
|
+
|
|
97
|
+
### Keep content in Rails.
|
|
98
|
+
|
|
99
|
+
Give editors the tools they need without giving up the application stack you
|
|
100
|
+
want.
|
|
101
|
+
|
|
102
|
+
Primary action: **Read the getting-started guide**
|
|
103
|
+
|
|
104
|
+
Secondary action: **Explore the roadmap**
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# plumcms.org Information Architecture
|
|
2
|
+
|
|
3
|
+
The site serves three audiences: developers adding content to an existing Rails
|
|
4
|
+
application, developers building a content-first site, and agencies operating
|
|
5
|
+
multiple client sites.
|
|
6
|
+
|
|
7
|
+
## Primary Navigation
|
|
8
|
+
|
|
9
|
+
- Why Plum
|
|
10
|
+
- Use Cases
|
|
11
|
+
- Documentation
|
|
12
|
+
- Roadmap
|
|
13
|
+
- GitHub
|
|
14
|
+
|
|
15
|
+
The persistent primary action is **Get started**.
|
|
16
|
+
|
|
17
|
+
## Routes
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
/
|
|
21
|
+
/why-plum
|
|
22
|
+
/features
|
|
23
|
+
/use-cases
|
|
24
|
+
/existing-rails-apps
|
|
25
|
+
/content-sites
|
|
26
|
+
/agencies
|
|
27
|
+
/docs
|
|
28
|
+
/getting-started
|
|
29
|
+
/concepts
|
|
30
|
+
/content-modeling
|
|
31
|
+
/themes
|
|
32
|
+
/embedding
|
|
33
|
+
/deployment
|
|
34
|
+
/reference
|
|
35
|
+
/roadmap
|
|
36
|
+
/changelog
|
|
37
|
+
/demo
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Homepage Story
|
|
41
|
+
|
|
42
|
+
The homepage should answer five questions in order:
|
|
43
|
+
|
|
44
|
+
1. What is Plum?
|
|
45
|
+
2. Why would a Rails developer use it instead of another CMS?
|
|
46
|
+
3. Can it work in my kind of project?
|
|
47
|
+
4. What does the code and editing experience look like?
|
|
48
|
+
5. Can I trust and try it?
|
|
49
|
+
|
|
50
|
+
## Documentation Structure
|
|
51
|
+
|
|
52
|
+
### Start
|
|
53
|
+
|
|
54
|
+
- Introduction
|
|
55
|
+
- Installation
|
|
56
|
+
- Your first editable page
|
|
57
|
+
- Build a small content site
|
|
58
|
+
|
|
59
|
+
### Core concepts
|
|
60
|
+
|
|
61
|
+
- Sites
|
|
62
|
+
- Content types and blueprints
|
|
63
|
+
- Entries and publishing
|
|
64
|
+
- Fields
|
|
65
|
+
- Liquid rendering
|
|
66
|
+
|
|
67
|
+
### Content features
|
|
68
|
+
|
|
69
|
+
- Blocks
|
|
70
|
+
- Rich text
|
|
71
|
+
- Assets and images
|
|
72
|
+
- Relationships
|
|
73
|
+
- Taxonomies
|
|
74
|
+
- Navigation
|
|
75
|
+
- Globals
|
|
76
|
+
- Forms
|
|
77
|
+
|
|
78
|
+
### Themes
|
|
79
|
+
|
|
80
|
+
- Theme anatomy
|
|
81
|
+
- Templates and layouts
|
|
82
|
+
- Theme manifests
|
|
83
|
+
- Settings
|
|
84
|
+
- Assets
|
|
85
|
+
- Blocks
|
|
86
|
+
- Packaging and installation
|
|
87
|
+
|
|
88
|
+
### Embed Plum
|
|
89
|
+
|
|
90
|
+
- Mounting the engine
|
|
91
|
+
- Host authentication
|
|
92
|
+
- Authorization
|
|
93
|
+
- Site resolution and tenancy
|
|
94
|
+
- Host content sources
|
|
95
|
+
- Routes and URLs
|
|
96
|
+
- White labelling
|
|
97
|
+
|
|
98
|
+
### Operate
|
|
99
|
+
|
|
100
|
+
- SQLite deployment
|
|
101
|
+
- PostgreSQL deployment
|
|
102
|
+
- Active Storage
|
|
103
|
+
- Jobs and email
|
|
104
|
+
- Docker and ONCE
|
|
105
|
+
- Backups and restore
|
|
106
|
+
- Upgrading
|
|
107
|
+
|
|
108
|
+
### Reference
|
|
109
|
+
|
|
110
|
+
- Configuration
|
|
111
|
+
- Blueprint field contracts
|
|
112
|
+
- Liquid objects and filters
|
|
113
|
+
- Theme manifest
|
|
114
|
+
- Generators
|
|
115
|
+
- Troubleshooting
|
|
116
|
+
|
|
117
|
+
## Content Types
|
|
118
|
+
|
|
119
|
+
### Pages
|
|
120
|
+
|
|
121
|
+
- Title
|
|
122
|
+
- Slug
|
|
123
|
+
- Summary
|
|
124
|
+
- Sections (`blocks`)
|
|
125
|
+
- SEO title
|
|
126
|
+
- SEO description
|
|
127
|
+
|
|
128
|
+
### Documentation pages
|
|
129
|
+
|
|
130
|
+
- Title
|
|
131
|
+
- Slug
|
|
132
|
+
- Section taxonomy
|
|
133
|
+
- Parent relationship
|
|
134
|
+
- Position
|
|
135
|
+
- Summary
|
|
136
|
+
- Body
|
|
137
|
+
|
|
138
|
+
### Releases
|
|
139
|
+
|
|
140
|
+
- Version
|
|
141
|
+
- Published date
|
|
142
|
+
- Summary
|
|
143
|
+
- Body
|
|
144
|
+
|
|
145
|
+
### Roadmap items
|
|
146
|
+
|
|
147
|
+
- Title
|
|
148
|
+
- Horizon (`now`, `next`, or `later`)
|
|
149
|
+
- Status
|
|
150
|
+
- Problem
|
|
151
|
+
- Intended outcome
|
|
152
|
+
|
|
153
|
+
## Initial Blocks
|
|
154
|
+
|
|
155
|
+
- Hero
|
|
156
|
+
- Prose
|
|
157
|
+
- Code example
|
|
158
|
+
- Feature grid
|
|
159
|
+
- Use-case cards
|
|
160
|
+
- Steps
|
|
161
|
+
- Comparison
|
|
162
|
+
- Quote
|
|
163
|
+
- Call to action
|
|
164
|
+
|
|
165
|
+
Blocks should be general enough to ship as examples or reusable base blocks.
|
|
166
|
+
Site-specific styling belongs in the plumcms.org theme.
|
|
167
|
+
|
|
168
|
+
## Proof the Site Must Provide
|
|
169
|
+
|
|
170
|
+
- The homepage is editable through Plum.
|
|
171
|
+
- Documentation is navigable and pleasant to read.
|
|
172
|
+
- A visitor can see real installation code immediately.
|
|
173
|
+
- The public roadmap distinguishes current capability from future intent.
|
|
174
|
+
- The application runs on Rails and SQLite in production.
|
|
175
|
+
- Its container, persistence, backup, and restore approach are documented.
|
|
176
|
+
- No private Plum features or site-specific engine patches are required.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Statamic capability parity
|
|
2
|
+
|
|
3
|
+
This matrix tracks practical authoring parity rather than matching Statamic's
|
|
4
|
+
internal architecture or naming.
|
|
5
|
+
|
|
6
|
+
| Capability | Plum status | Notes |
|
|
7
|
+
|---|---|---|
|
|
8
|
+
| Blueprint field builder | Supported | Visual, nested, typed configuration |
|
|
9
|
+
| Reusable fieldsets | Supported | Site-scoped snapshots with collision-safe insertion |
|
|
10
|
+
| Field instructions/defaults/required | Supported | Client and server validation |
|
|
11
|
+
| Field widths and sections | Supported | Twelve-column responsive editor |
|
|
12
|
+
| Conditional fields | Supported | Five common operators |
|
|
13
|
+
| Text, rich text, numbers, dates | Supported | Bounds and modes included |
|
|
14
|
+
| Choice controls | Supported | Select, radio, buttons, checkboxes |
|
|
15
|
+
| Assets | Supported | Single/multi-image fields, metadata, focal points, variants |
|
|
16
|
+
| Relationships | Supported | Single/multiple, type-filtered, site-scoped |
|
|
17
|
+
| Structured content | Supported | Lists, groups, repeaters, blocks |
|
|
18
|
+
| Taxonomies | Supported | Managed terms and public archives |
|
|
19
|
+
| Globals and navigation | Supported | Liquid-accessible content |
|
|
20
|
+
| Forms | Supported | Definitions, submissions, notifications |
|
|
21
|
+
| Themes | Supported | Liquid packages, settings, blocks |
|
|
22
|
+
| Revisions and publishing workflow | Supported | Attributed snapshots, restoration, drafts, scheduling |
|
|
23
|
+
| Localization/multisite | Supported | Site locales, translation groups, localized URLs/API |
|
|
24
|
+
| Content API | Supported | Public, site-scoped, live-only JSON collections |
|
|
25
|
+
| Addon field types | Supported | Registry-backed editor and value pipeline |
|
|
26
|
+
|
|
27
|
+
Longer-term ecosystem work can add commercial-style addon discovery, more
|
|
28
|
+
workflow roles, and translation services without changing these authoring APIs.
|
data/docs/vision.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Plum's Vision
|
|
2
|
+
|
|
3
|
+
Plum is the Rails-native CMS.
|
|
4
|
+
|
|
5
|
+
It gives Rails developers a default way to add managed content to an existing
|
|
6
|
+
application or build a complete content-first site without introducing another
|
|
7
|
+
application stack.
|
|
8
|
+
|
|
9
|
+
## Why Plum Exists
|
|
10
|
+
|
|
11
|
+
Rails is excellent at building applications, but content management is still
|
|
12
|
+
usually assembled from bespoke admin screens, delegated to a remote headless
|
|
13
|
+
CMS, or moved into a separate publishing platform. Each choice adds work or
|
|
14
|
+
pulls content away from the application that uses it.
|
|
15
|
+
|
|
16
|
+
Plum makes content a native part of Rails. It uses the application's database,
|
|
17
|
+
models, users, authorization, jobs, mail, storage, and deployment environment.
|
|
18
|
+
Developers keep the flexibility of Ruby and Rails. Editors get a focused,
|
|
19
|
+
polished place to manage content.
|
|
20
|
+
|
|
21
|
+
## Who Plum Is For
|
|
22
|
+
|
|
23
|
+
### Rails application teams
|
|
24
|
+
|
|
25
|
+
Mount Plum inside an existing application to manage marketing pages,
|
|
26
|
+
documentation, announcements, navigation, help content, and other editorial
|
|
27
|
+
material. Application records can be exposed safely alongside managed content
|
|
28
|
+
without copying them into an external CMS.
|
|
29
|
+
|
|
30
|
+
### Independent developers and agencies
|
|
31
|
+
|
|
32
|
+
Use Plum as the foundation of a complete client site. Start with Rails, SQLite,
|
|
33
|
+
a Plum theme, and one deployable container. Retain the ability to add ordinary
|
|
34
|
+
Rails features when the project grows beyond a brochure site.
|
|
35
|
+
|
|
36
|
+
### SaaS products
|
|
37
|
+
|
|
38
|
+
Give each account a site-scoped, white-labelled editing experience while the
|
|
39
|
+
host application continues to own identity, authorization, tenancy, and
|
|
40
|
+
business data.
|
|
41
|
+
|
|
42
|
+
## The Promise
|
|
43
|
+
|
|
44
|
+
A developer should be able to add Plum to a Rails application and publish an
|
|
45
|
+
editable page in less than ten minutes.
|
|
46
|
+
|
|
47
|
+
A small content site should be able to run as one Rails application with SQLite
|
|
48
|
+
and persistent storage. An agency should be able to operate several independent
|
|
49
|
+
Plum sites on one VM as portable containers. A larger application should be
|
|
50
|
+
able to use PostgreSQL and embed Plum without changing its content model.
|
|
51
|
+
|
|
52
|
+
Content must remain portable. Plum should never require a hosted Plum account,
|
|
53
|
+
a proprietary runtime, or a second frontend application.
|
|
54
|
+
|
|
55
|
+
## What Makes Plum Different
|
|
56
|
+
|
|
57
|
+
- It is Rails infrastructure, not a remote content service.
|
|
58
|
+
- It works both as a mountable engine and as the center of a standalone site.
|
|
59
|
+
- It lets editorial content and host application data participate in the same
|
|
60
|
+
rendering context.
|
|
61
|
+
- It follows the Rails approach: strong conventions, ordinary Ruby extension
|
|
62
|
+
points, and ownership of the complete application.
|
|
63
|
+
- It supports a low-operations SQLite path without limiting applications that
|
|
64
|
+
need PostgreSQL.
|
|
65
|
+
- It treats themes, content, assets, backups, and deployments as portable parts
|
|
66
|
+
of a site rather than features of a vendor account.
|
|
67
|
+
|
|
68
|
+
## The Long-Term Goal
|
|
69
|
+
|
|
70
|
+
When a Rails developer asks, "How do I let someone edit this content?", Plum
|
|
71
|
+
should be the obvious answer.
|
|
72
|
+
|
|
73
|
+
Plum succeeds when it becomes normal to:
|
|
74
|
+
|
|
75
|
+
- mount Plum in a Rails product;
|
|
76
|
+
- start a client content site with Plum;
|
|
77
|
+
- publish and share Plum themes and blocks;
|
|
78
|
+
- run a collection of independent Plum sites economically; and
|
|
79
|
+
- extend content workflows with familiar Rails code.
|
|
80
|
+
|
|
81
|
+
The goal is not to reproduce every feature of every CMS. The goal is to make
|
|
82
|
+
content management feel like it has always belonged in Rails.
|
data/lib/plum/version.rb
CHANGED
data/lib/plum.rb
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require "fileutils"
|
|
2
|
+
|
|
3
|
+
namespace :plum do
|
|
4
|
+
desc "Build Tailwind and copy the result into Plum's packaged stylesheet"
|
|
5
|
+
task build_styles: :environment do
|
|
6
|
+
system(Rails.root.join("bin/rails").to_s, "tailwindcss:build", exception: true)
|
|
7
|
+
source = Rails.root.join("app/assets/builds/tailwind.css")
|
|
8
|
+
destination = Rails.root.join("app/assets/stylesheets/plum/control_panel.css")
|
|
9
|
+
FileUtils.cp(source, destination)
|
|
10
|
+
puts "Packaged #{destination.relative_path_from(Rails.root)}"
|
|
11
|
+
end
|
|
12
|
+
end
|