rivet_cms 0.1.0.pre

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 (58) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/builds/rivet_cms.css +2 -0
  6. data/app/assets/builds/rivet_cms.js +9536 -0
  7. data/app/assets/builds/rivet_cms.js.map +7 -0
  8. data/app/assets/stylesheets/rivet_cms/application.tailwind.css +25 -0
  9. data/app/assets/stylesheets/rivet_cms/brand_colors.css +168 -0
  10. data/app/controllers/rivet_cms/api/docs_controller.rb +38 -0
  11. data/app/controllers/rivet_cms/application_controller.rb +5 -0
  12. data/app/controllers/rivet_cms/components_controller.rb +7 -0
  13. data/app/controllers/rivet_cms/content_types_controller.rb +61 -0
  14. data/app/controllers/rivet_cms/dashboard_controller.rb +10 -0
  15. data/app/controllers/rivet_cms/fields_controller.rb +109 -0
  16. data/app/helpers/rivet_cms/application_helper.rb +7 -0
  17. data/app/helpers/rivet_cms/brand_color_helper.rb +71 -0
  18. data/app/helpers/rivet_cms/flash_helper.rb +37 -0
  19. data/app/helpers/rivet_cms/sign_out_helper.rb +11 -0
  20. data/app/javascript/controllers/content_type_form_controller.js +53 -0
  21. data/app/javascript/controllers/field_layout_controller.js +709 -0
  22. data/app/javascript/rivet_cms.js +29 -0
  23. data/app/jobs/rivet_cms/application_job.rb +4 -0
  24. data/app/mailers/rivet_cms/application_mailer.rb +6 -0
  25. data/app/models/rivet_cms/application_record.rb +5 -0
  26. data/app/models/rivet_cms/component.rb +4 -0
  27. data/app/models/rivet_cms/content.rb +4 -0
  28. data/app/models/rivet_cms/content_type.rb +40 -0
  29. data/app/models/rivet_cms/content_value.rb +4 -0
  30. data/app/models/rivet_cms/field.rb +82 -0
  31. data/app/models/rivet_cms/field_values/base.rb +11 -0
  32. data/app/models/rivet_cms/field_values/boolean.rb +4 -0
  33. data/app/models/rivet_cms/field_values/integer.rb +4 -0
  34. data/app/models/rivet_cms/field_values/string.rb +4 -0
  35. data/app/models/rivet_cms/field_values/text.rb +4 -0
  36. data/app/services/rivet_cms/open_api_generator.rb +245 -0
  37. data/app/views/layouts/rivet_cms/application.html.erb +49 -0
  38. data/app/views/rivet_cms/api/docs/show.html.erb +47 -0
  39. data/app/views/rivet_cms/content_types/_form.html.erb +98 -0
  40. data/app/views/rivet_cms/content_types/edit.html.erb +27 -0
  41. data/app/views/rivet_cms/content_types/index.html.erb +151 -0
  42. data/app/views/rivet_cms/content_types/new.html.erb +19 -0
  43. data/app/views/rivet_cms/content_types/show.html.erb +147 -0
  44. data/app/views/rivet_cms/dashboard/index.html.erb +263 -0
  45. data/app/views/rivet_cms/fields/_form.html.erb +111 -0
  46. data/app/views/rivet_cms/fields/edit.html.erb +25 -0
  47. data/app/views/rivet_cms/fields/index.html.erb +126 -0
  48. data/app/views/rivet_cms/fields/new.html.erb +25 -0
  49. data/app/views/rivet_cms/shared/_navigation.html.erb +153 -0
  50. data/config/i18n-tasks.yml +178 -0
  51. data/config/locales/en.yml +14 -0
  52. data/config/routes.rb +56 -0
  53. data/db/migrate/20250317194359_create_core_tables.rb +90 -0
  54. data/lib/rivet_cms/engine.rb +55 -0
  55. data/lib/rivet_cms/version.rb +3 -0
  56. data/lib/rivet_cms.rb +44 -0
  57. data/lib/tasks/rivet_cms_tasks.rake +4 -0
  58. metadata +231 -0
@@ -0,0 +1,178 @@
1
+ # i18n-tasks finds and manages missing and unused translations: https://github.com/glebm/i18n-tasks
2
+
3
+ # The "main" locale.
4
+ base_locale: en
5
+ ## All available locales are inferred from the data by default. Alternatively, specify them explicitly:
6
+ # locales: [es, fr]
7
+ ## Reporting locale, default: en. Available: en, ru.
8
+ # internal_locale: en
9
+
10
+ # Read and write translations.
11
+ data:
12
+ ## Translations are read from the file system. Supported format: YAML, JSON.
13
+ ## Provide a custom adapter:
14
+ # adapter: I18n::Tasks::Data::FileSystem
15
+
16
+ # Locale files or `Dir.glob` patterns where translations are read from:
17
+ read:
18
+ ## Default:
19
+ # - config/locales/%{locale}.yml
20
+ ## More files:
21
+ # - config/locales/**/*.%{locale}.yml
22
+
23
+ # Locale files to write new keys to, based on a list of key pattern => file rules. Matched from top to bottom:
24
+ # `i18n-tasks normalize -p` will force move the keys according to these rules
25
+ write:
26
+ ## For example, write devise and simple form keys to their respective files:
27
+ # - ['{devise, simple_form}.*', 'config/locales/\1.%{locale}.yml']
28
+ ## Catch-all default:
29
+ # - config/locales/%{locale}.yml
30
+
31
+ # External locale data (e.g. gems).
32
+ # This data is not considered unused and is never written to.
33
+ external:
34
+ ## Example (replace %#= with %=):
35
+ # - "<%#= %x[bundle info vagrant --path].chomp %>/templates/locales/%{locale}.yml"
36
+
37
+ ## Specify the router (see Readme for details). Valid values: conservative_router, pattern_router, isolating_router, or a custom class.
38
+ # router: conservative_router
39
+
40
+ yaml:
41
+ write:
42
+ # do not wrap lines at 80 characters
43
+ line_width: -1
44
+
45
+ ## Pretty-print JSON:
46
+ # json:
47
+ # write:
48
+ # indent: ' '
49
+ # space: ' '
50
+ # object_nl: "\n"
51
+ # array_nl: "\n"
52
+
53
+ # Find translate calls
54
+ search:
55
+ ## Paths or `Find.find` patterns to search in:
56
+ # paths:
57
+ # - app/
58
+
59
+ ## Root directories for relative keys resolution.
60
+ # relative_roots:
61
+ # - app/controllers
62
+ # - app/helpers
63
+ # - app/mailers
64
+ # - app/presenters
65
+ # - app/views
66
+
67
+ ## Directories where method names which should not be part of a relative key resolution.
68
+ # By default, if a relative translation is used inside a method, the name of the method will be considered part of the resolved key.
69
+ # Directories listed here will not consider the name of the method part of the resolved key
70
+ #
71
+ # relative_exclude_method_name_paths:
72
+ # -
73
+
74
+ ## Files or `File.fnmatch` patterns to exclude from search. Some files are always excluded regardless of this setting:
75
+ ## *.jpg *.jpeg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less
76
+ ## *.yml *.json *.zip *.tar.gz *.swf *.flv *.mp3 *.wav *.flac *.webm *.mp4 *.ogg *.opus *.webp *.map *.xlsx
77
+ exclude:
78
+ - app/assets/images
79
+ - app/assets/fonts
80
+ - app/assets/videos
81
+ - app/assets/builds
82
+
83
+ ## Alternatively, the only files or `File.fnmatch patterns` to search in `paths`:
84
+ ## If specified, this settings takes priority over `exclude`, but `exclude` still applies.
85
+ # only: ["*.rb", "*.html.slim"]
86
+
87
+ ## If `strict` is `false`, guess usages such as t("categories.#{category}.title"). The default is `true`.
88
+ # strict: true
89
+
90
+ ## Allows adding ast_matchers for finding translations using the AST-scanners
91
+ ## The available matchers are:
92
+ ## - RailsModelMatcher
93
+ ## Matches ActiveRecord translations like
94
+ ## User.human_attribute_name(:email) and User.model_name.human
95
+ ## - DefaultI18nSubjectMatcher
96
+ ## Matches ActionMailer's default_i18n_subject method
97
+ ##
98
+ ## To implement your own, please see `I18n::Tasks::Scanners::AstMatchers::BaseMatcher`.
99
+ # ast_matchers:
100
+ # - 'I18n::Tasks::Scanners::AstMatchers::RailsModelMatcher'
101
+ # - 'I18n::Tasks::Scanners::AstMatchers::DefaultI18nSubjectMatcher'
102
+
103
+ ## Multiple scanners can be used. Their results are merged.
104
+ ## The options specified above are passed down to each scanner. Per-scanner options can be specified as well.
105
+ ## See this example of a custom scanner: https://github.com/glebm/i18n-tasks/wiki/A-custom-scanner-example
106
+
107
+ ## Translation Services
108
+ # translation:
109
+ # # Google Translate
110
+ # # Get an API key and set billing info at https://code.google.com/apis/console to use Google Translate
111
+ # google_translate_api_key: "AbC-dEf5"
112
+ # # DeepL Pro Translate
113
+ # # Get an API key and subscription at https://www.deepl.com/pro to use DeepL Pro
114
+ # deepl_api_key: "48E92789-57A3-466A-9959-1A1A1A1A1A1A"
115
+ # # deepl_host: "https://api.deepl.com"
116
+ # # deepl_version: "v2"
117
+ # # deepl_glossary_ids:
118
+ # # - f28106eb-0e06-489e-82c6-8215d6f95089
119
+ # # - 2c6415be-1852-4f54-9e1b-d800463496b4
120
+ # # add additional options to the DeepL.translate call: https://www.deepl.com/docs-api/translate-text/translate-text/
121
+ # deepl_options:
122
+ # formality: prefer_less
123
+ # # OpenAI
124
+ # openai_api_key: "sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
125
+ # # openai_model: "gpt-4o-mini" # see https://platform.openai.com/docs/models
126
+ # # may contain `%{from}` and `%{to}`, which will be replaced by source and target locale codes, respectively (using `Kernel.format`)
127
+ # # openai_system_prompt: >-
128
+ # # You are a professional translator that translates content from the %{from} locale
129
+ # # to the %{to} locale in an i18n locale array.
130
+ # #
131
+ # # The array has a structured format and contains multiple strings. Your task is to translate
132
+ # # each of these strings and create a new array with the translated strings.
133
+ # #
134
+ # # HTML markups (enclosed in < and > characters) must not be changed under any circumstance.
135
+ # # Variables (starting with %%{ and ending with }) must not be changed under any circumstance.
136
+ # #
137
+ # # Keep in mind the context of all the strings for a more accurate translation.
138
+
139
+ ## Do not consider these keys missing:
140
+ # ignore_missing:
141
+ # - 'errors.messages.{accepted,blank,invalid,too_short,too_long}'
142
+ # - '{devise,simple_form}.*'
143
+
144
+ ## Consider these keys used:
145
+ # ignore_unused:
146
+ # - 'activerecord.attributes.*'
147
+ # - '{devise,kaminari,will_paginate}.*'
148
+ # - 'simple_form.{yes,no}'
149
+ # - 'simple_form.{placeholders,hints,labels}.*'
150
+ # - 'simple_form.{error_notification,required}.:'
151
+
152
+ ## Exclude these keys from the `i18n-tasks eq-base' report:
153
+ # ignore_eq_base:
154
+ # all:
155
+ # - common.ok
156
+ # fr,es:
157
+ # - common.brand
158
+
159
+ ## Exclude these keys from the `i18n-tasks check-consistent-interpolations` report:
160
+ # ignore_inconsistent_interpolations:
161
+ # - 'activerecord.attributes.*'
162
+
163
+ ## Ignore these keys completely:
164
+ # ignore:
165
+ # - kaminari.*
166
+
167
+ ## Sometimes, it isn't possible for i18n-tasks to match the key correctly,
168
+ ## e.g. in case of a relative key defined in a helper method.
169
+ ## In these cases you can use the built-in PatternMapper to map patterns to keys, e.g.:
170
+ #
171
+ # <%# I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
172
+ # only: %w(*.html.haml *.html.slim),
173
+ # patterns: [['= title\b', '.page_title']] %>
174
+ #
175
+ # The PatternMapper can also match key literals via a special %{key} interpolation, e.g.:
176
+ #
177
+ # <%# I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
178
+ # patterns: [['\bSpree\.t[( ]\s*%{key}', 'spree.%{key}']] %>
@@ -0,0 +1,14 @@
1
+ ---
2
+ en:
3
+ rivet_cms:
4
+ shared:
5
+ navigation:
6
+ api_docs: Api Docs
7
+ components: Components
8
+ components_short: Comp
9
+ content: Content
10
+ content_types: Content Types
11
+ content_types_short: Types
12
+ dashboard: Dashboard
13
+ media: Media
14
+ users: Users
data/config/routes.rb ADDED
@@ -0,0 +1,56 @@
1
+ RivetCms::Engine.register_routes do
2
+ get '/', to: "dashboard#index", as: :dashboard
3
+
4
+ # Content Type Management
5
+ resources :content_types, path: 'content-types' do
6
+ resources :fields, except: [:show] do
7
+ collection do
8
+ post :update_positions
9
+ end
10
+ member do
11
+ patch :update_width
12
+ end
13
+ end
14
+ resources :contents
15
+ end
16
+
17
+ # Component Management
18
+ resources :components do
19
+ resources :fields, except: [:show] do
20
+ collection do
21
+ post :update_positions
22
+ end
23
+ end
24
+ end
25
+
26
+ # API Documentation
27
+ namespace :api do
28
+ resource :docs, only: [:show]
29
+ end
30
+
31
+ # Helper method to check if content type exists and matches the collection/single type
32
+ content_type_exists = ->(slug, is_collection) {
33
+ RivetCMS::ContentType.exists?(slug: slug, is_single: !is_collection)
34
+ }
35
+
36
+ # API routes with versioning
37
+ namespace :api do
38
+ namespace :v1 do
39
+ # Dynamic routes for content types
40
+ get ':slug', to: 'content#index', constraints: ->(req) { content_type_exists.call(req.params[:slug], true) }
41
+ post ':slug', to: 'content#create', constraints: ->(req) { content_type_exists.call(req.params[:slug], true) }
42
+ get ':slug/:id', to: 'content#show', constraints: ->(req) { content_type_exists.call(req.params[:slug], true) }
43
+ put ':slug/:id', to: 'content#update', constraints: ->(req) { content_type_exists.call(req.params[:slug], true) }
44
+ patch ':slug/:id', to: 'content#update', constraints: ->(req) { content_type_exists.call(req.params[:slug], true) }
45
+ delete ':slug/:id', to: 'content#destroy', constraints: ->(req) { content_type_exists.call(req.params[:slug], true) }
46
+
47
+ # Routes for single type content
48
+ get ':slug', to: 'single#show', constraints: ->(req) { content_type_exists.call(req.params[:slug], false) }
49
+ put ':slug', to: 'single#update', constraints: ->(req) { content_type_exists.call(req.params[:slug], false) }
50
+ patch ':slug', to: 'single#update', constraints: ->(req) { content_type_exists.call(req.params[:slug], false) }
51
+ post ':slug', to: 'single#update', constraints: ->(req) { content_type_exists.call(req.params[:slug], false) }
52
+ end
53
+ end
54
+ end
55
+
56
+ RivetCms::Engine.draw_routes
@@ -0,0 +1,90 @@
1
+ class CreateCoreTables < ActiveRecord::Migration[7.2]
2
+ def change
3
+ def json_or_text
4
+ if connection.adapter_name.downcase == "mysql2"
5
+ mysql_version = connection.select_value("SELECT VERSION()")
6
+ Gem::Version.new(mysql_version) >= Gem::Version.new("5.7.8") ? :json : :text
7
+ else
8
+ :jsonb
9
+ end
10
+ end
11
+
12
+ create_table :rivet_cms_content_types do |t|
13
+ t.string :name, null: false
14
+ t.string :slug, null: false
15
+ t.text :description
16
+ t.boolean :is_single, default: false
17
+ t.timestamps
18
+
19
+ t.index :slug, unique: true
20
+ end
21
+
22
+ create_table :rivet_cms_components do |t|
23
+ t.string :name, null: false
24
+ t.string :slug, null: false
25
+ t.text :description
26
+ t.boolean :repeatable, default: false
27
+ t.timestamps
28
+
29
+ t.index :slug, unique: true
30
+ end
31
+
32
+ create_table :rivet_cms_fields do |t|
33
+ t.references :component, null: true, foreign_key: { to_table: :rivet_cms_components }
34
+ t.references :content_type, null: true, foreign_key: { to_table: :rivet_cms_content_types }
35
+ t.string :name, null: false
36
+ t.string :field_type, null: false
37
+ t.text :description
38
+ t.boolean :required, default: false
39
+ t.column :options, json_or_text, default: {}
40
+ t.integer :position
41
+ t.string :width, default: "full"
42
+ t.integer :row_group
43
+ t.timestamps
44
+
45
+ t.index [:content_type_id, :name], unique: true, name: "index_fields_on_content_type_id_and_name"
46
+ t.index [:component_id, :name], unique: true, name: "index_fields_on_component_id_and_name"
47
+ t.index :position
48
+ t.check_constraint "(component_id IS NOT NULL AND content_type_id IS NULL) OR (component_id IS NULL AND content_type_id IS NOT NULL)", name: "field_owner_check"
49
+ end
50
+
51
+ create_table :rivet_cms_contents do |t|
52
+ t.references :content_type, null: false, foreign_key: { to_table: :rivet_cms_content_types }
53
+ t.string :slug, null: false
54
+ t.string :status, null: false, default: "draft"
55
+ t.datetime :published_at
56
+ t.datetime :unpublished_at
57
+ t.timestamps
58
+
59
+ t.index :slug, unique: true
60
+ t.index :status
61
+ end
62
+
63
+ create_table :rivet_cms_content_values do |t|
64
+ t.references :content, null: false, foreign_key: { to_table: :rivet_cms_contents }
65
+ t.references :field, null: false, foreign_key: { to_table: :rivet_cms_fields }
66
+ t.references :value, polymorphic: true, null: false
67
+ t.timestamps
68
+ end
69
+
70
+ create_table :rivet_cms_field_values_strings do |t|
71
+ t.string :value, null: false
72
+ t.timestamps
73
+ end
74
+
75
+ create_table :rivet_cms_field_values_texts do |t|
76
+ t.text :value, null: false
77
+ t.timestamps
78
+ end
79
+
80
+ create_table :rivet_cms_field_values_booleans do |t|
81
+ t.boolean :value, null: false
82
+ t.timestamps
83
+ end
84
+
85
+ create_table :rivet_cms_field_values_integers do |t|
86
+ t.integer :value, null: false
87
+ t.timestamps
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,55 @@
1
+ # lib/rivet_cms/engine.rb
2
+ require "image_processing"
3
+ require "prefixed_ids"
4
+ require "kaminari"
5
+ require "turbo-rails"
6
+ require "stimulus-rails"
7
+
8
+ module RivetCms
9
+ class Engine < ::Rails::Engine
10
+ isolate_namespace RivetCms
11
+
12
+ # Configure internationalization before the engine loads
13
+ config.before_configuration do
14
+ config.i18n.load_path += Dir[File.join(File.dirname(__FILE__), '..', 'config', 'locales', '**', '*.yml')]
15
+ end
16
+
17
+ # Set up testing and factory configurations
18
+ config.generators do |g|
19
+ g.test_framework :rspec
20
+ g.fixture_replacement :factory_bot
21
+ g.factory_bot dir: 'spec/factories'
22
+ end
23
+
24
+ class << self
25
+ # Accessor for the routes storage
26
+ def routes_storage
27
+ # Use a class-level instance variable with a default empty array
28
+ @routes_storage ||= []
29
+ end
30
+
31
+ # Register route definitions to be drawn later
32
+ # @param block [Proc] A block containing route definitions
33
+ def register_routes(&block)
34
+ routes_storage << block # Add the block to the storage
35
+ end
36
+
37
+ # Draw all registered routes into the engine's RouteSet
38
+ def draw_routes
39
+ # Capture the routes in a local variable before entering the block
40
+ stored_routes = routes_storage
41
+
42
+ # Use the engine's routes.draw method to provide the proper routing context
43
+ routes.draw do
44
+ # Iterate over the captured routes
45
+ stored_routes.each do |route_block|
46
+ instance_eval(&route_block)
47
+ end
48
+ end
49
+
50
+ # Clear the routes to prevent re-drawing if called again
51
+ routes_storage.clear
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,3 @@
1
+ module RivetCms
2
+ VERSION = "0.1.0.pre"
3
+ end
data/lib/rivet_cms.rb ADDED
@@ -0,0 +1,44 @@
1
+ require "rivet_cms/version"
2
+ require "rivet_cms/engine"
3
+
4
+ module RivetCms
5
+ class << self
6
+ def configuration
7
+ @configuration ||= Configuration.new
8
+ end
9
+
10
+ def configuration=(config)
11
+ @configuration = config
12
+ end
13
+ end
14
+
15
+ def self.configure
16
+ self.configuration ||= Configuration.new
17
+ yield(configuration) if block_given?
18
+ validate_user_class(configuration.user_class)
19
+ end
20
+
21
+ class Configuration
22
+ attr_accessor :user_class, :image_variants, :default_roles, :current_user_method,
23
+ :prefixed_ids_length, :prefixed_ids_salt, :prefixed_ids_alphabet,
24
+ :sign_out_path
25
+
26
+ def initialize
27
+ @user_class = "RivetCmsAuth::User"
28
+ @image_variants = {
29
+ thumbnail: { width: 100, height: 100, resize: "fit" },
30
+ medium: { width: 800, height: 600, resize: "limit" }
31
+ }
32
+ @default_roles = %w[admin editor contributor]
33
+ @current_user_method = "current_user"
34
+ @prefixed_ids_length = 32
35
+ @prefixed_ids_salt = "rivet-cms-#{Rails.env}"
36
+ @prefixed_ids_alphabet = "0123456789abcdefghijklmnopqrstuvwxyz"
37
+ @sign_out_path = if defined?(RivetCmsAuth::Engine)
38
+ lambda { RivetCmsAuth::Engine.routes.url_helpers.auth_sign_out_path }
39
+ else
40
+ "/" # Default to root if no auth engine
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :rivet_cms do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,231 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rivet_cms
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.pre
5
+ platform: ruby
6
+ authors:
7
+ - Nathan Williams
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-03-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '7.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '7.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: image_processing
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: prefixed_ids
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: kaminari
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: turbo-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: stimulus-rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec-rails
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: factory_bot_rails
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: i18n-tasks
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: Rivet CMS is a powerful headless CMS engine for Ruby on Rails. It provides
140
+ a flexible content management system with dynamic content types, API-first architecture,
141
+ and a modern admin interface.
142
+ email:
143
+ - nathan@nathan.la
144
+ executables: []
145
+ extensions: []
146
+ extra_rdoc_files: []
147
+ files:
148
+ - MIT-LICENSE
149
+ - README.md
150
+ - Rakefile
151
+ - app/assets/builds/rivet_cms.css
152
+ - app/assets/builds/rivet_cms.js
153
+ - app/assets/builds/rivet_cms.js.map
154
+ - app/assets/stylesheets/rivet_cms/application.tailwind.css
155
+ - app/assets/stylesheets/rivet_cms/brand_colors.css
156
+ - app/controllers/rivet_cms/api/docs_controller.rb
157
+ - app/controllers/rivet_cms/application_controller.rb
158
+ - app/controllers/rivet_cms/components_controller.rb
159
+ - app/controllers/rivet_cms/content_types_controller.rb
160
+ - app/controllers/rivet_cms/dashboard_controller.rb
161
+ - app/controllers/rivet_cms/fields_controller.rb
162
+ - app/helpers/rivet_cms/application_helper.rb
163
+ - app/helpers/rivet_cms/brand_color_helper.rb
164
+ - app/helpers/rivet_cms/flash_helper.rb
165
+ - app/helpers/rivet_cms/sign_out_helper.rb
166
+ - app/javascript/controllers/content_type_form_controller.js
167
+ - app/javascript/controllers/field_layout_controller.js
168
+ - app/javascript/rivet_cms.js
169
+ - app/jobs/rivet_cms/application_job.rb
170
+ - app/mailers/rivet_cms/application_mailer.rb
171
+ - app/models/rivet_cms/application_record.rb
172
+ - app/models/rivet_cms/component.rb
173
+ - app/models/rivet_cms/content.rb
174
+ - app/models/rivet_cms/content_type.rb
175
+ - app/models/rivet_cms/content_value.rb
176
+ - app/models/rivet_cms/field.rb
177
+ - app/models/rivet_cms/field_values/base.rb
178
+ - app/models/rivet_cms/field_values/boolean.rb
179
+ - app/models/rivet_cms/field_values/integer.rb
180
+ - app/models/rivet_cms/field_values/string.rb
181
+ - app/models/rivet_cms/field_values/text.rb
182
+ - app/services/rivet_cms/open_api_generator.rb
183
+ - app/views/layouts/rivet_cms/application.html.erb
184
+ - app/views/rivet_cms/api/docs/show.html.erb
185
+ - app/views/rivet_cms/content_types/_form.html.erb
186
+ - app/views/rivet_cms/content_types/edit.html.erb
187
+ - app/views/rivet_cms/content_types/index.html.erb
188
+ - app/views/rivet_cms/content_types/new.html.erb
189
+ - app/views/rivet_cms/content_types/show.html.erb
190
+ - app/views/rivet_cms/dashboard/index.html.erb
191
+ - app/views/rivet_cms/fields/_form.html.erb
192
+ - app/views/rivet_cms/fields/edit.html.erb
193
+ - app/views/rivet_cms/fields/index.html.erb
194
+ - app/views/rivet_cms/fields/new.html.erb
195
+ - app/views/rivet_cms/shared/_navigation.html.erb
196
+ - config/i18n-tasks.yml
197
+ - config/locales/en.yml
198
+ - config/routes.rb
199
+ - db/migrate/20250317194359_create_core_tables.rb
200
+ - lib/rivet_cms.rb
201
+ - lib/rivet_cms/engine.rb
202
+ - lib/rivet_cms/version.rb
203
+ - lib/tasks/rivet_cms_tasks.rake
204
+ homepage: https://github.com/narch/rivet_cms
205
+ licenses:
206
+ - MIT
207
+ metadata:
208
+ allowed_push_host: https://rubygems.org
209
+ homepage_uri: https://github.com/narch/rivet_cms
210
+ source_code_uri: https://github.com/narch/rivet_cms
211
+ changelog_uri: https://github.com/narch/rivet_cms/blob/main/CHANGELOG.md
212
+ post_install_message:
213
+ rdoc_options: []
214
+ require_paths:
215
+ - lib
216
+ required_ruby_version: !ruby/object:Gem::Requirement
217
+ requirements:
218
+ - - ">="
219
+ - !ruby/object:Gem::Version
220
+ version: '0'
221
+ required_rubygems_version: !ruby/object:Gem::Requirement
222
+ requirements:
223
+ - - ">"
224
+ - !ruby/object:Gem::Version
225
+ version: 1.3.1
226
+ requirements: []
227
+ rubygems_version: 3.4.10
228
+ signing_key:
229
+ specification_version: 4
230
+ summary: A modern, flexible headless CMS engine for Ruby on Rails
231
+ test_files: []