trek 0.1.21 → 0.1.22
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/.npmignore +3 -0
- data/Gemfile.lock +76 -74
- data/README.md +8 -0
- data/app/assets/stylesheets/trek/_colors.css +181 -0
- data/app/components/trek/button_component.rb +9 -3
- data/app/components/trek/form/actions_component/actions_component.css +6 -0
- data/app/components/trek/form/image_field_component/image_field_component.css +1 -1
- data/app/components/trek/form/switch_box_component.rb +1 -0
- data/app/components/trek/tabs_component/tabs_component.css +1 -0
- data/app/controllers/concerns/trek/model.rb +4 -1
- data/config/locales/trek.en.yml +2 -0
- data/docs/.vitepress/config.mjs +133 -0
- data/docs/.vitepress/theme/index.js +17 -0
- data/docs/.vitepress/theme/style.css +139 -0
- data/docs/customize.md +63 -7
- data/docs/getting-started.md +160 -0
- data/docs/index.md +39 -0
- data/docs/public/logo.svg +1 -0
- data/docs/reference/components.md +40 -0
- data/docs/reference/concerns/contentable.md +28 -0
- data/docs/reference/concerns/formattable.md +24 -0
- data/docs/reference/concerns/fragmentable.md +33 -0
- data/docs/reference/concerns/keyable.md +18 -0
- data/docs/reference/concerns/orderable.md +26 -0
- data/docs/reference/concerns/pageable.md +35 -0
- data/docs/reference/concerns/pathable.md +28 -0
- data/docs/reference/concerns/phonable.md +28 -0
- data/docs/reference/concerns/search-engine-optimizable.md +19 -0
- data/docs/reference/concerns/searchable.md +22 -0
- data/docs/reference/concerns/sectionable.md +24 -0
- data/docs/reference/concerns/sluggable.md +21 -0
- data/docs/reference/concerns/taggable.md +20 -0
- data/docs/reference/concerns/translatable.md +35 -0
- data/docs/reference/concerns/versionable.md +27 -0
- data/docs/reference/controllers.md +23 -0
- data/docs/reference/environment-variables.md +9 -0
- data/docs/reference/formatters.md +30 -0
- data/docs/reference/forms.md +21 -0
- data/docs/reference/generators/admin-user.md +17 -0
- data/docs/reference/generators/install.md +42 -0
- data/docs/reference/generators/scaffold.md +37 -0
- data/docs/reference/generators/taxonomies.md +21 -0
- data/docs/reference/icons.md +11 -0
- data/docs/reference/index.md +47 -0
- data/docs/reference/models/current.md +11 -0
- data/docs/reference/models/external-link.md +16 -0
- data/docs/reference/models/fragment.md +28 -0
- data/docs/reference/models/menu-node.md +30 -0
- data/docs/reference/models/page-path.md +19 -0
- data/docs/reference/models/page-version.md +30 -0
- data/docs/reference/models/page.md +48 -0
- data/docs/reference/models/tag.md +41 -0
- data/docs/reference/models/user.md +65 -0
- data/docs/reference/policies.md +30 -0
- data/docs/reference/uploaders.md +19 -0
- data/docs/what-is-trek.md +37 -0
- data/esbuild.config.js +10 -7
- data/lib/trek/version.rb +1 -1
- data/netlify.toml +4 -0
- data/package.json +10 -5
- data/renovate.json +4 -0
- data/yarn.lock +2015 -235
- metadata +48 -2
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Fragment
|
|
2
|
+
|
|
3
|
+
Reusable chunks of content — a footer text, a hero tagline, a contact blurb — editable from the admin and usable anywhere in your views. Fragments are grouped by `namespace` and identified by `key`.
|
|
4
|
+
|
|
5
|
+
## Columns
|
|
6
|
+
|
|
7
|
+
| Column | Type | Notes |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `key` | string | unique within its namespace |
|
|
10
|
+
| `namespace` | string | grouping (e.g. `footer`, `home`) |
|
|
11
|
+
| `title` | jsonb | translated label |
|
|
12
|
+
| `content` | jsonb | ProseMirror document |
|
|
13
|
+
| `position` | integer | ordering within the namespace |
|
|
14
|
+
|
|
15
|
+
## Behavior
|
|
16
|
+
|
|
17
|
+
- Includes [Contentable](/reference/concerns/contentable), [Translatable](/reference/concerns/translatable) (`title`, `content`), [Keyable](/reference/concerns/keyable) and `strip_attributes`
|
|
18
|
+
- `acts_as_list scope: [:namespace]` with an `ordered` scope
|
|
19
|
+
- `to_s` returns `"namespace.key"`
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
fragment = Fragment.find_by(namespace: "footer", key: "tagline")
|
|
25
|
+
fragment.formatted_content # => safe HTML
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Pages can also be composed from fragments via the [Fragmentable](/reference/concerns/fragmentable) concern and the `page_fragments` configuration matrix.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# MenuNode
|
|
2
|
+
|
|
3
|
+
Hierarchical menu builder: each node links to a [Page](/reference/models/page), an [ExternalLink](/reference/models/external-link), or any custom linkable model.
|
|
4
|
+
|
|
5
|
+
## Columns
|
|
6
|
+
|
|
7
|
+
| Column | Type | Notes |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `key` | string | unique within its parent, optional |
|
|
10
|
+
| `title` / `label` | jsonb | translated texts |
|
|
11
|
+
| `parent_id` | bigint | tree hierarchy |
|
|
12
|
+
| `position` | integer | ordering among siblings |
|
|
13
|
+
| `linkable_type` / `linkable_id` | string / bigint | polymorphic target |
|
|
14
|
+
| `icon_key` | string | optional [icon](/reference/icons) |
|
|
15
|
+
| `modifiers` | string | styling flags |
|
|
16
|
+
|
|
17
|
+
## Behavior
|
|
18
|
+
|
|
19
|
+
- `has_closure_tree` for the hierarchy, [Orderable](/reference/concerns/orderable) for positions
|
|
20
|
+
- `belongs_to :linkable, polymorphic: true, optional: true`
|
|
21
|
+
- Includes [Translatable](/reference/concerns/translatable) and `strip_attributes`
|
|
22
|
+
|
|
23
|
+
## Notable methods
|
|
24
|
+
|
|
25
|
+
| Method | Returns |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| `to_s` | title, label or key |
|
|
28
|
+
| `to_param` | key or id |
|
|
29
|
+
| `icon?` / `icon` | whether an icon is set / the `IconComponent` for it |
|
|
30
|
+
| `external_link?` | whether the target is an `ExternalLink` |
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# PagePath
|
|
2
|
+
|
|
3
|
+
Stable, translatable URLs for [pages](/reference/models/page). Trek keeps every path a page has ever had, so old URLs keep working (redirecting to the current one) after a page is renamed or moved.
|
|
4
|
+
|
|
5
|
+
## Columns
|
|
6
|
+
|
|
7
|
+
| Column | Type | Notes |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `page_id` | bigint | required |
|
|
10
|
+
| `path` | jsonb | translated full path (e.g. `services/design`) |
|
|
11
|
+
|
|
12
|
+
## Behavior
|
|
13
|
+
|
|
14
|
+
- `belongs_to :page` — all historical paths of the page
|
|
15
|
+
- `has_one :current_page` — the page this path is the *current* path for (via `pages.current_path_id`)
|
|
16
|
+
- Includes [Translatable](/reference/concerns/translatable) — paths are localized per locale
|
|
17
|
+
- Records are created and updated automatically by the page's `after_save_commit` callback; you never manage them by hand
|
|
18
|
+
|
|
19
|
+
See [Pathable](/reference/concerns/pathable) for the page-side API (`full_path`, `find_at_full_path`…).
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# PageVersion
|
|
2
|
+
|
|
3
|
+
Version history for [pages](/reference/models/page): every snapshot of a versioned page's content and image. There is always exactly one *current* version per page; the others are archived.
|
|
4
|
+
|
|
5
|
+
## Columns
|
|
6
|
+
|
|
7
|
+
| Column | Type | Notes |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `page_id` | bigint | required |
|
|
10
|
+
| `name` | string | version label, auto-generated from the page title and date |
|
|
11
|
+
| `content` | jsonb | ProseMirror content snapshot |
|
|
12
|
+
| `image_data` | jsonb | Shrine attachment snapshot |
|
|
13
|
+
| `current_since` | datetime | set ⇔ this is the current version |
|
|
14
|
+
|
|
15
|
+
## Behavior
|
|
16
|
+
|
|
17
|
+
- `belongs_to :page` — with `Page#versions` ordered most recent first
|
|
18
|
+
- Validations guarantee **one and only one** current version per page
|
|
19
|
+
- `after_initialize` sets a default name like `"Page title (2026-06-10)"`
|
|
20
|
+
- Includes [Sectionable](/reference/concerns/sectionable), `RecordImageUploader::Attachment(:image)` and `strip_attributes`
|
|
21
|
+
|
|
22
|
+
## Notable methods
|
|
23
|
+
|
|
24
|
+
| Method | Returns |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| `current?` | whether this version is the live one |
|
|
27
|
+
| `other_versions` | the page's other versions |
|
|
28
|
+
| `current_image` / `current_image_url` | this version's image |
|
|
29
|
+
|
|
30
|
+
See [Versionable](/reference/concerns/versionable) for the page-side API (`create_current_version_from_page!`, `current_content`…).
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Page
|
|
2
|
+
|
|
3
|
+
Hierarchical, translatable content pages with SEO metadata, versioning and stable URL paths. Generated into `app/models/page.rb`.
|
|
4
|
+
|
|
5
|
+
## Columns
|
|
6
|
+
|
|
7
|
+
| Column | Type | Notes |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `key` | string | internal identifier, optional |
|
|
10
|
+
| `slug` | jsonb | translated URL slug |
|
|
11
|
+
| `title` | jsonb | translated title |
|
|
12
|
+
| `description` | jsonb | translated description |
|
|
13
|
+
| `content` | jsonb | ProseMirror document |
|
|
14
|
+
| `pageable_type` / `pageable_id` | string / bigint | polymorphic link to a content model |
|
|
15
|
+
| `parent_id` | bigint | tree hierarchy |
|
|
16
|
+
| `position` | integer | ordering among siblings |
|
|
17
|
+
| `image_data` | jsonb | Shrine attachment |
|
|
18
|
+
| `versioned` | boolean | enables [versioning](/reference/concerns/versionable), default `false` |
|
|
19
|
+
| `sectioned` | boolean | enables [sections](/reference/concerns/sectionable), default `false` |
|
|
20
|
+
| `current_path_id` | bigint | current [PagePath](/reference/models/page-path) |
|
|
21
|
+
|
|
22
|
+
## Included concerns
|
|
23
|
+
|
|
24
|
+
[Translatable](/reference/concerns/translatable) (`slug`, `title`, `description`), [Formattable](/reference/concerns/formattable), [Contentable](/reference/concerns/contentable), [Fragmentable](/reference/concerns/fragmentable), [Orderable](/reference/concerns/orderable), [Pathable](/reference/concerns/pathable), [SearchEngineOptimizable](/reference/concerns/search-engine-optimizable), [Sectionable](/reference/concerns/sectionable), [Sluggable](/reference/concerns/sluggable), [Versionable](/reference/concerns/versionable), [Keyable](/reference/concerns/keyable), plus `RecordImageUploader::Attachment(:image)` and `strip_attributes`.
|
|
25
|
+
|
|
26
|
+
## Associations
|
|
27
|
+
|
|
28
|
+
- `has_closure_tree` — parent/children hierarchy (siblings, ancestors, descendants)
|
|
29
|
+
- `belongs_to :pageable, polymorphic: true, optional: true` — the content model this page represents (see [Pageable](/reference/concerns/pageable))
|
|
30
|
+
- `has_many :versions` → [PageVersion](/reference/models/page-version)
|
|
31
|
+
- `has_many :paths` and `belongs_to :current_path` → [PagePath](/reference/models/page-path)
|
|
32
|
+
- `has_many :menu_nodes, as: :linkable` → [MenuNode](/reference/models/menu-node)
|
|
33
|
+
|
|
34
|
+
## Validations & scopes
|
|
35
|
+
|
|
36
|
+
- `title` presence; `slug` presence (unless root) and uniqueness within the parent
|
|
37
|
+
- `alpha_ordered` — orders by translated title in the current locale
|
|
38
|
+
|
|
39
|
+
## Notable methods
|
|
40
|
+
|
|
41
|
+
| Method | Returns |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| `full_path` | the page's current URL path |
|
|
44
|
+
| `find_at_full_path(path)` | class method — page lookup by path |
|
|
45
|
+
| `parsed_content` / `formatted_content` / `content_text` | ProseMirror content as hash / HTML / plain text |
|
|
46
|
+
| `current_version` / `current_content` / `current_image` | versioned content accessors |
|
|
47
|
+
| `seo_values` / `meta_tags` | SEO metadata with fallbacks |
|
|
48
|
+
| `fragments` | the [fragments](/reference/models/fragment) attached to this page key |
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Tag, TagCategory & Tagging
|
|
2
|
+
|
|
3
|
+
The taxonomy models, installed by the [taxonomies generator](/reference/generators/taxonomies). Make any model taggable with the [Taggable](/reference/concerns/taggable) concern.
|
|
4
|
+
|
|
5
|
+
## Tag
|
|
6
|
+
|
|
7
|
+
| Column | Type | Notes |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `key` | string | required, unique within its category |
|
|
10
|
+
| `name` | string | required display name |
|
|
11
|
+
| `category_id` | bigint | optional [TagCategory](#tagcategory) |
|
|
12
|
+
| `position` | integer | ordering within the category |
|
|
13
|
+
| `taggings_count` | integer | counter cache |
|
|
14
|
+
|
|
15
|
+
- `belongs_to :category`, `has_many :taggings`, `has_many :taggables, through: :taggings`
|
|
16
|
+
- Scopes: `ordered`, `in_category(key)`, `in_categories(keys)`
|
|
17
|
+
|
|
18
|
+
## TagCategory
|
|
19
|
+
|
|
20
|
+
| Column | Type | Notes |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| `key` | string | required, unique |
|
|
23
|
+
| `name` | string | required display name |
|
|
24
|
+
| `position` | integer | ordering |
|
|
25
|
+
| `tags_count` | integer | counter cache |
|
|
26
|
+
|
|
27
|
+
- `has_many :tags` (ordered)
|
|
28
|
+
- Scopes: `ordered`, `with_tags`
|
|
29
|
+
|
|
30
|
+
## Tagging
|
|
31
|
+
|
|
32
|
+
The polymorphic join between a `Tag` and any taggable record, unique per (`taggable`, `tag`) pair, with counter caches on both sides.
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
class Article < ApplicationRecord
|
|
36
|
+
include Trek::Taggable
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
article.tags << Tag.in_category("topics").first
|
|
40
|
+
article.tag_names # => ["Ruby"]
|
|
41
|
+
```
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# User
|
|
2
|
+
|
|
3
|
+
The host application's `User` model, into which Trek injects authentication (Sorcery), roles, theme & locale preferences and the invitation workflow.
|
|
4
|
+
|
|
5
|
+
## Columns added by Trek
|
|
6
|
+
|
|
7
|
+
| Column | Type | Notes |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `name` | string | display name |
|
|
10
|
+
| `role` | integer | enum, default `guest` |
|
|
11
|
+
| `theme` | integer | enum, default `auto` |
|
|
12
|
+
| `locale` | string | admin UI language |
|
|
13
|
+
|
|
14
|
+
Plus the Sorcery authentication columns (`email`, `crypted_password`, reset tokens…).
|
|
15
|
+
|
|
16
|
+
## Roles
|
|
17
|
+
|
|
18
|
+
`Trek::Users::Roles` defines the role enum and access levels:
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
enum :role, { admin: 5, editor: 4, user: 3, reader: 2, guest: 1 }, default: "guest"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- `privileged?` — `true` for `admin` and `editor`; this is what the default [policies](/reference/policies) check
|
|
25
|
+
- `User.human_roles` — translated role names for form selects
|
|
26
|
+
|
|
27
|
+
## Themes
|
|
28
|
+
|
|
29
|
+
`Trek::Users::Themes` lets each user pick the admin theme:
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
enum :theme, { auto: 0, light: 1, dark: 2 }, default: "auto"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`User.human_themes` returns translated theme names.
|
|
36
|
+
|
|
37
|
+
## Locales
|
|
38
|
+
|
|
39
|
+
`Trek::Users::Locales` provides `User.human_locales` — the available admin UI languages with translated labels, sourced from `I18n.available_locales`.
|
|
40
|
+
|
|
41
|
+
## Invitations
|
|
42
|
+
|
|
43
|
+
`Trek::Users::Invitable` adds a transient `send_invite` flag: when set on creation, the user receives an invitation email with a password-reset link.
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
User.create(email: "new@example.com", role: :editor, send_invite: true)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Validations
|
|
50
|
+
|
|
51
|
+
`Trek::Users::Validations` enforces:
|
|
52
|
+
|
|
53
|
+
- `email` — presence, uniqueness, valid format
|
|
54
|
+
- `password` — minimum 8 characters (on creation or password change)
|
|
55
|
+
|
|
56
|
+
## Scopes
|
|
57
|
+
|
|
58
|
+
`Trek::Users::Scopes` adds `User.ordered` — alphabetical by name, then email.
|
|
59
|
+
|
|
60
|
+
## Form models
|
|
61
|
+
|
|
62
|
+
Two non-persisted `ActiveModel::Model` companions handle the auth flows:
|
|
63
|
+
|
|
64
|
+
- **`Trek::UserSession`** — `email` + `password`, used by the login form
|
|
65
|
+
- **`Trek::UserPasswordReset`** — `email`, looks up the `user` to send a reset link to
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Policies
|
|
2
|
+
|
|
3
|
+
Authorization relies on [ActionPolicy](https://actionpolicy.evilmartians.io). Trek provides `Trek::ApplicationPolicy`, `Trek::ResourcePolicy` and policies for its own models (`PagePolicy`, `FragmentPolicy`, `UserPolicy`).
|
|
4
|
+
|
|
5
|
+
Scaffolded policies inherit from `Trek::ResourcePolicy` and control access per [role](/reference/models/user#roles):
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
module Admin
|
|
9
|
+
class BookPolicy < Trek::ResourcePolicy
|
|
10
|
+
def index? = user.privileged?
|
|
11
|
+
def create? = user.privileged?
|
|
12
|
+
def manage? = user.privileged?
|
|
13
|
+
def destroy? = user.privileged?
|
|
14
|
+
|
|
15
|
+
def permitted_attributes
|
|
16
|
+
user.privileged? ? %i[title intro] : []
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
relation_scope do |relation|
|
|
20
|
+
next relation if user.privileged?
|
|
21
|
+
|
|
22
|
+
relation.none
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- `permitted_attributes` doubles as strong parameters: `Trek::ResourceController` only permits what the policy allows for the current user.
|
|
29
|
+
- `relation_scope` filters index queries per role.
|
|
30
|
+
- `user.privileged?` is true for the `admin` and `editor` roles.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Uploaders
|
|
2
|
+
|
|
3
|
+
File uploads are handled by [Shrine](https://shrinerb.com), with Uppy on the front-end:
|
|
4
|
+
|
|
5
|
+
- `ImageUploader` — base image uploader
|
|
6
|
+
- `RecordImageUploader` — attach an image to any record: `include RecordImageUploader::Attachment(:image)`
|
|
7
|
+
- `ModelImageUploader` — model-level image uploader (used by content editor images)
|
|
8
|
+
|
|
9
|
+
## Storage
|
|
10
|
+
|
|
11
|
+
Configured per environment in the generated Shrine initializer (`config/initializers/shrine.rb`):
|
|
12
|
+
|
|
13
|
+
| Environment | Storage |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| production | S3 (via the [`S3_*` ENV variables](/reference/environment-variables)) |
|
|
16
|
+
| development | local filesystem (`public/uploads/`) |
|
|
17
|
+
| test | in-memory |
|
|
18
|
+
|
|
19
|
+
Image processing uses libvips, blurhash placeholders are generated for progressive loading, and direct uploads go through the Shrine `upload_endpoint` (20 MB max).
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# What's Trek?
|
|
2
|
+
|
|
3
|
+
Trek is a modern content management & back-office system for Ruby on Rails, built by [Etamin Studio](https://etamin.studio). It is designed to get you started fast with useful conventions, then let you customize the back-office to your project's needs.
|
|
4
|
+
|
|
5
|
+
Trek ships as a Rails engine (a gem plus an NPM package) that integrates into your own Rails application. Unlike hosted CMSs, your content lives in your database, your models stay plain Active Record, and everything remains customizable with regular Rails code.
|
|
6
|
+
|
|
7
|
+
## What you get
|
|
8
|
+
|
|
9
|
+
- **A complete admin panel** — layout, navigation, search, pagination, light & dark themes, all built with [ViewComponent](https://viewcomponent.org), [Stimulus](https://stimulus.hotwired.dev) and [Turbo](https://turbo.hotwired.dev).
|
|
10
|
+
- **Pages** — hierarchical, translatable pages with version history, SEO metadata and stable, redirect-aware URL paths.
|
|
11
|
+
- **Fragments** — reusable chunks of content (a footer text, a hero tagline…) editable from the admin and usable anywhere in your views.
|
|
12
|
+
- **A rich text editor** — based on [Tiptap](https://tiptap.dev), with image uploads (Uppy), link insertion and content stored as structured ProseMirror JSON.
|
|
13
|
+
- **Authentication & authorization** — [Sorcery](https://github.com/Sorcery/sorcery)-based sign in, password resets, invitations, and [ActionPolicy](https://actionpolicy.evilmartians.io) policies with `admin`, `editor`, `user`, `reader` and `guest` roles.
|
|
14
|
+
- **Internationalization** — content translations with [Mobility](https://github.com/shioyama/mobility), locale management with [i18n-tasks](https://github.com/glebm/i18n-tasks), and optional automatic translation through DeepL.
|
|
15
|
+
- **File uploads** — [Shrine](https://shrinerb.com)-backed attachments with S3 or local storage, image processing via libvips, and blurhash placeholders.
|
|
16
|
+
- **Generators** — an installer that sets up everything above, and a scaffold generator that creates a full admin panel for any model in one command.
|
|
17
|
+
|
|
18
|
+
## Philosophy
|
|
19
|
+
|
|
20
|
+
Trek follows the Rails way:
|
|
21
|
+
|
|
22
|
+
- **Convention over configuration.** The installer makes opinionated choices (PostgreSQL, Slim, esbuild, PostCSS, RSpec, Standard…) so you don't have to. Every choice can be revisited afterwards — the generated code lives in your application.
|
|
23
|
+
- **Code generation over runtime magic.** Models like `User`, `Page` or `Fragment` are generated into your app with their concerns included, rather than hidden inside the engine. You can read them, edit them, and remove what you don't need.
|
|
24
|
+
- **Progressive customization.** Start with the defaults, then override views, components, policies or styles as your project grows.
|
|
25
|
+
|
|
26
|
+
## Requirements
|
|
27
|
+
|
|
28
|
+
| Dependency | Version |
|
|
29
|
+
| --- | --- |
|
|
30
|
+
| Ruby | 3.1+ |
|
|
31
|
+
| Rails | 7.0+ |
|
|
32
|
+
| PostgreSQL | 12+ |
|
|
33
|
+
| Node | 20+ |
|
|
34
|
+
| Yarn | 3.x |
|
|
35
|
+
| libvips | — |
|
|
36
|
+
|
|
37
|
+
Ready to try it? Head over to the [quick start](/getting-started).
|
data/esbuild.config.js
CHANGED
|
@@ -7,7 +7,9 @@ if (process.env.NODE_ENV === undefined) {
|
|
|
7
7
|
process.env.NODE_ENV = process.env.RAILS_ENV || "development";
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
const watch = process.argv.includes("--watch");
|
|
11
|
+
|
|
12
|
+
const options = {
|
|
11
13
|
plugins: [
|
|
12
14
|
rails(),
|
|
13
15
|
postCssPlugin({
|
|
@@ -17,8 +19,7 @@ let config = esbuild.build({
|
|
|
17
19
|
entryPoints: glob("app/javascript/*.*"),
|
|
18
20
|
bundle: true,
|
|
19
21
|
platform: "browser",
|
|
20
|
-
|
|
21
|
-
sourcemap: !process.argv.includes("--watch"),
|
|
22
|
+
sourcemap: !watch,
|
|
22
23
|
outdir: "app/assets/builds",
|
|
23
24
|
loader: {
|
|
24
25
|
".png": "file",
|
|
@@ -28,9 +29,11 @@ let config = esbuild.build({
|
|
|
28
29
|
},
|
|
29
30
|
logLevel: "debug",
|
|
30
31
|
minify: process.env.NODE_ENV === "production",
|
|
31
|
-
define: { DEBUG: process.env.NODE_ENV !== "production" },
|
|
32
|
-
}
|
|
32
|
+
define: { DEBUG: JSON.stringify(process.env.NODE_ENV !== "production") },
|
|
33
|
+
};
|
|
33
34
|
|
|
34
|
-
if (
|
|
35
|
-
|
|
35
|
+
if (watch) {
|
|
36
|
+
esbuild.context(options).then((ctx) => ctx.watch());
|
|
37
|
+
} else {
|
|
38
|
+
esbuild.build(options).catch(() => process.exit(1));
|
|
36
39
|
}
|
data/lib/trek/version.rb
CHANGED
data/netlify.toml
ADDED
data/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etaminstudio/trek",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.22",
|
|
4
4
|
"description": "A modern CMS for Ruby on Rails",
|
|
5
5
|
"main": "app/javascript/trek.js",
|
|
6
6
|
"repository": {
|
|
@@ -30,8 +30,7 @@
|
|
|
30
30
|
"tom-select": "^2.2.2"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"esbuild": "^0.
|
|
34
|
-
"esbuild-plugin-import-glob": "^0.1.1",
|
|
33
|
+
"esbuild": "^0.28.0",
|
|
35
34
|
"esbuild-rails": "^1.0.7",
|
|
36
35
|
"esbuild-style-plugin": "^1.6.3",
|
|
37
36
|
"eslint": "^8.49.0",
|
|
@@ -48,7 +47,13 @@
|
|
|
48
47
|
"prettier": "2.8.8",
|
|
49
48
|
"stylelint": "^15.11.0",
|
|
50
49
|
"stylelint-config-standard": "^31.0.0",
|
|
51
|
-
"stylelint-order": "^6.0.4"
|
|
50
|
+
"stylelint-order": "^6.0.4",
|
|
51
|
+
"vitepress": "^1.6.4"
|
|
52
52
|
},
|
|
53
|
-
"packageManager": "yarn@3.8.0"
|
|
53
|
+
"packageManager": "yarn@3.8.0",
|
|
54
|
+
"scripts": {
|
|
55
|
+
"docs:dev": "vitepress dev docs",
|
|
56
|
+
"docs:build": "vitepress build docs",
|
|
57
|
+
"docs:preview": "vitepress preview docs"
|
|
58
|
+
}
|
|
54
59
|
}
|
data/renovate.json
ADDED