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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/README.md +66 -3
  4. data/app/assets/builds/tailwind.css +1 -1
  5. data/app/assets/stylesheets/plum/control_panel.css +1 -1
  6. data/app/assets/tailwind/application.css +42 -0
  7. data/app/controllers/plum/api/v1/entries_controller.rb +48 -0
  8. data/app/controllers/plum/cp/assets_controller.rb +4 -1
  9. data/app/controllers/plum/cp/content_types_controller.rb +25 -2
  10. data/app/controllers/plum/cp/entries_controller.rb +119 -9
  11. data/app/controllers/plum/cp/entry_revisions_controller.rb +27 -0
  12. data/app/controllers/plum/cp/fieldsets_controller.rb +37 -0
  13. data/app/controllers/plum/cp/site_settings_controller.rb +20 -1
  14. data/app/controllers/plum/pages_controller.rb +26 -1
  15. data/app/javascript/controllers/plum/asset_collection_controller.js +18 -0
  16. data/app/javascript/controllers/plum/blueprint_controller.js +202 -25
  17. data/app/javascript/controllers/plum/conditional_fields_controller.js +43 -0
  18. data/app/javascript/controllers/plum/focal_point_controller.js +16 -0
  19. data/app/javascript/controllers/plum/structured_field_controller.js +133 -0
  20. data/app/models/plum/asset.rb +5 -1
  21. data/app/models/plum/content_type.rb +63 -1
  22. data/app/models/plum/entry.rb +225 -1
  23. data/app/models/plum/entry_revision.rb +14 -0
  24. data/app/models/plum/fieldset.rb +17 -0
  25. data/app/models/plum/site.rb +15 -0
  26. data/app/models/plum/user.rb +1 -0
  27. data/app/services/plum/entry_serializer.rb +36 -0
  28. data/app/services/plum/field_expander.rb +12 -1
  29. data/app/services/plum/field_options.rb +21 -0
  30. data/app/services/plum/field_type_registry.rb +88 -0
  31. data/app/services/plum/liquid_context.rb +7 -1
  32. data/app/views/layouts/plum/cp.html.erb +2 -0
  33. data/app/views/plum/cp/assets/_form.html.erb +13 -1
  34. data/app/views/plum/cp/content_types/_form.html.erb +81 -24
  35. data/app/views/plum/cp/custom_fields/_input.html.erb +5 -0
  36. data/app/views/plum/cp/entries/_form.html.erb +108 -31
  37. data/app/views/plum/cp/entries/edit.html.erb +16 -0
  38. data/app/views/plum/cp/entry_revisions/index.html.erb +25 -0
  39. data/app/views/plum/cp/fieldsets/index.html.erb +30 -0
  40. data/app/views/plum/cp/site_settings/edit.html.erb +12 -0
  41. data/config/plum_routes.rb +15 -0
  42. data/db/engine_migrate/20260807130000_create_plum_entry_revisions.rb +16 -0
  43. data/db/engine_migrate/20260807140000_create_plum_fieldsets.rb +13 -0
  44. data/db/engine_migrate/20260807150000_add_focal_point_to_plum_assets.rb +6 -0
  45. data/db/engine_migrate/20260807160000_add_localization_to_plum_entries.rb +9 -0
  46. data/docs/blueprint-fields.md +55 -0
  47. data/docs/extensions.md +32 -0
  48. data/docs/product-principles.md +73 -0
  49. data/docs/roadmap.md +98 -0
  50. data/docs/site/homepage.md +104 -0
  51. data/docs/site/information-architecture.md +176 -0
  52. data/docs/statamic-parity.md +28 -0
  53. data/docs/vision.md +82 -0
  54. data/lib/plum/version.rb +1 -1
  55. data/lib/plum.rb +4 -0
  56. data/lib/tasks/plum_styles.rake +12 -0
  57. 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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  module Plum
2
2
  module Version
3
- STRING = "0.1.2"
3
+ STRING = "0.2.0"
4
4
  end
5
5
 
6
6
  VERSION = Version::STRING
data/lib/plum.rb CHANGED
@@ -6,6 +6,10 @@ module Plum
6
6
  def self.table_name_prefix
7
7
  "plum_"
8
8
  end
9
+
10
+ def self.register_field_type(**options)
11
+ FieldTypeRegistry.register(**options)
12
+ end
9
13
  end
10
14
 
11
15
  require_relative "plum/engine" if defined?(Rails::Engine)
@@ -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