trek 0.1.20 → 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.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.npmignore +3 -0
  3. data/Gemfile.lock +86 -82
  4. data/README.md +8 -0
  5. data/app/assets/stylesheets/trek/_colors.css +181 -0
  6. data/app/components/trek/button_component.rb +9 -3
  7. data/app/components/trek/dashboard/tile_component/tile_component.html.slim +1 -1
  8. data/app/components/trek/dashboard/tile_component.rb +2 -0
  9. data/app/components/trek/form/actions_component/actions_component.css +6 -0
  10. data/app/components/trek/form/image_field_component/image_field_component.css +8 -0
  11. data/app/components/trek/form/image_field_component/image_field_component.html.slim +20 -8
  12. data/app/components/trek/form/image_field_component/image_field_component.js +23 -1
  13. data/app/components/trek/form/image_field_component.rb +13 -0
  14. data/app/components/trek/form/switch_box_component.rb +1 -0
  15. data/app/components/trek/tabs_component/tabs_component.css +1 -0
  16. data/app/controllers/concerns/trek/model.rb +4 -1
  17. data/config/locales/trek.en.yml +3 -0
  18. data/config/locales/trek.fr.yml +1 -0
  19. data/docs/.vitepress/config.mjs +133 -0
  20. data/docs/.vitepress/theme/index.js +17 -0
  21. data/docs/.vitepress/theme/style.css +139 -0
  22. data/docs/customize.md +63 -7
  23. data/docs/getting-started.md +160 -0
  24. data/docs/index.md +39 -0
  25. data/docs/public/logo.svg +1 -0
  26. data/docs/reference/components.md +40 -0
  27. data/docs/reference/concerns/contentable.md +28 -0
  28. data/docs/reference/concerns/formattable.md +24 -0
  29. data/docs/reference/concerns/fragmentable.md +33 -0
  30. data/docs/reference/concerns/keyable.md +18 -0
  31. data/docs/reference/concerns/orderable.md +26 -0
  32. data/docs/reference/concerns/pageable.md +35 -0
  33. data/docs/reference/concerns/pathable.md +28 -0
  34. data/docs/reference/concerns/phonable.md +28 -0
  35. data/docs/reference/concerns/search-engine-optimizable.md +19 -0
  36. data/docs/reference/concerns/searchable.md +22 -0
  37. data/docs/reference/concerns/sectionable.md +24 -0
  38. data/docs/reference/concerns/sluggable.md +21 -0
  39. data/docs/reference/concerns/taggable.md +20 -0
  40. data/docs/reference/concerns/translatable.md +35 -0
  41. data/docs/reference/concerns/versionable.md +27 -0
  42. data/docs/reference/controllers.md +23 -0
  43. data/docs/reference/environment-variables.md +9 -0
  44. data/docs/reference/formatters.md +30 -0
  45. data/docs/reference/forms.md +21 -0
  46. data/docs/reference/generators/admin-user.md +17 -0
  47. data/docs/reference/generators/install.md +42 -0
  48. data/docs/reference/generators/scaffold.md +37 -0
  49. data/docs/reference/generators/taxonomies.md +21 -0
  50. data/docs/reference/icons.md +11 -0
  51. data/docs/reference/index.md +47 -0
  52. data/docs/reference/models/current.md +11 -0
  53. data/docs/reference/models/external-link.md +16 -0
  54. data/docs/reference/models/fragment.md +28 -0
  55. data/docs/reference/models/menu-node.md +30 -0
  56. data/docs/reference/models/page-path.md +19 -0
  57. data/docs/reference/models/page-version.md +30 -0
  58. data/docs/reference/models/page.md +48 -0
  59. data/docs/reference/models/tag.md +41 -0
  60. data/docs/reference/models/user.md +65 -0
  61. data/docs/reference/policies.md +30 -0
  62. data/docs/reference/uploaders.md +19 -0
  63. data/docs/what-is-trek.md +37 -0
  64. data/esbuild.config.js +10 -7
  65. data/lib/generators/trek/templates/initializers/shrine.rb +1 -0
  66. data/lib/trek/version.rb +1 -1
  67. data/netlify.toml +4 -0
  68. data/package.json +10 -5
  69. data/renovate.json +4 -0
  70. data/yarn.lock +2015 -235
  71. metadata +48 -2
@@ -8,7 +8,13 @@ import French from "@uppy/locales/lib/fr_FR";
8
8
  import "@uppy/core/dist/style.css";
9
9
 
10
10
  export class Controller extends BaseController {
11
- static targets = ["content", "fileInput", "hiddenInput", "preview"];
11
+ static targets = [
12
+ "content",
13
+ "fileInput",
14
+ "hiddenInput",
15
+ "preview",
16
+ "removeInput",
17
+ ];
12
18
 
13
19
  connect() {
14
20
  this.uppy = new Uppy({
@@ -48,6 +54,9 @@ export class Controller extends BaseController {
48
54
  const uploadedFileData = response.body["data"];
49
55
 
50
56
  this.hiddenInputTarget.value = JSON.stringify(uploadedFileData);
57
+
58
+ // Clear the remove flag when a new file is uploaded
59
+ this.removeInputTarget.value = "";
51
60
  });
52
61
 
53
62
  this.uppy.on("file-removed", () => {
@@ -64,6 +73,19 @@ export class Controller extends BaseController {
64
73
  this.uppy = null;
65
74
  }
66
75
 
76
+ removeImage() {
77
+ // Clear the cached upload data
78
+ this.hiddenInputTarget.value = "";
79
+
80
+ // Set the remove flag so Shrine deletes the attachment on save
81
+ this.removeInputTarget.value = "1";
82
+
83
+ // Reset preview to placeholder icon
84
+ this.previewTarget.innerHTML = `<svg class="c-trek--icon-root c-trek--icon-trek--pic" role="img" focusable="false">
85
+ <use xlink:href="#c-icon-trek--pic"></use>
86
+ </svg>`;
87
+ }
88
+
67
89
  addFiles(event) {
68
90
  const files = Array.from(event.target.files);
69
91
 
@@ -7,6 +7,13 @@ module Trek
7
7
  include StimulusHelpers
8
8
  include Turbo::FramesHelper
9
9
 
10
+ # Ensure the placeholder icon is in the sprite even when an image exists,
11
+ # because the JS removeImage action needs it.
12
+ def before_render
13
+ Current.icons ||= []
14
+ Current.icons << "trek--pic" unless Current.icons.include?("trek--pic")
15
+ end
16
+
10
17
  private
11
18
 
12
19
  def preview
@@ -48,6 +55,12 @@ module Trek
48
55
  }.merge(stimulus_target_hash("fileInput"))
49
56
  end
50
57
 
58
+ def remove_button_data_attributes
59
+ {
60
+ action: stimulus_action("removeImage")
61
+ }
62
+ end
63
+
51
64
  def button_text
52
65
  image&.exists? ? t("admin.actions.replace") : t("admin.actions.browse")
53
66
  end
@@ -53,6 +53,7 @@ module Trek
53
53
  end
54
54
 
55
55
  def label_text
56
+ content ||= options[:label]
56
57
  content ||= ActionView::Helpers::Tags::Translator.new(object, object_name, method_name, scope: "helpers.label").translate
57
58
  content ||= method_name.humanize
58
59
  content
@@ -1,6 +1,7 @@
1
1
  /* Use component-local class names and add them to HTML via #class_for(name) helper */
2
2
 
3
3
  .root {
4
+ margin-bottom: 10rem;
4
5
  max-width: 64rem;
5
6
  }
6
7
 
@@ -34,8 +34,11 @@ module Trek
34
34
  # Returns model element as an array of symbols for route building.
35
35
  # For namespaced models like Missive::List, returns [:missive, :list].
36
36
  # For non-namespaced models like Page, returns [:page].
37
+ # Derived from collection (which preserves namespace) rather than element
38
+ # (which demodulizes).
37
39
  def model_element_route
38
- model_name.element.split("/").map(&:to_sym)
40
+ parts = model_name.collection.split("/")
41
+ (parts[0...-1] + [parts.last.singularize]).map(&:to_sym)
39
42
  end
40
43
 
41
44
  def model_intro(action: nil)
@@ -43,6 +43,7 @@ en:
43
43
  n: New %{resource}
44
44
  reorder_resource:
45
45
  n: Reorder %{resources}
46
+ remove: Remove
46
47
  replace: Replace
47
48
  search_resource:
48
49
  n: Search for a %{resource}
@@ -215,10 +216,12 @@ en:
215
216
  h4: 4th-level title
216
217
  hard_break: Line break
217
218
  horizontal_rule: Horizontal line
219
+ image: Image
218
220
  italic: Italic
219
221
  link: Link
220
222
  paragraph: Paragraph
221
223
  placeholder: Write something…
224
+ prompt: Action
222
225
  redo: Redo the last operation
223
226
  undo: Undo the last operation
224
227
  list:
@@ -49,6 +49,7 @@ fr:
49
49
  f: Réorganiser les %{resources}
50
50
  m: Réorganiser les %{resources}
51
51
  m_alt: Réorganiser les %{resources}
52
+ remove: Enlever
52
53
  replace: Remplacer
53
54
  search_resource:
54
55
  "n": Rechercher un·e %{resources}
@@ -0,0 +1,133 @@
1
+ import { defineConfig } from 'vitepress'
2
+
3
+ // https://vitepress.dev/reference/site-config
4
+ export default defineConfig({
5
+ title: "Trek",
6
+ description: "A modern content management & back-office system for Ruby on Rails",
7
+ lang: 'en-US',
8
+ lastUpdated: true,
9
+ themeConfig: {
10
+ logo: { src: '/logo.svg', width: 24, height: 24 },
11
+
12
+ // https://vitepress.dev/reference/default-theme-config
13
+ nav: [
14
+ { text: 'Home', link: '/' },
15
+ { text: 'Guide', link: '/what-is-trek' },
16
+ { text: 'Reference', link: '/reference/' }
17
+ ],
18
+
19
+ sidebar: {
20
+ '/': [
21
+ {
22
+ text: 'Introduction',
23
+ items: [
24
+ { text: "What's Trek?", link: '/what-is-trek' },
25
+ { text: 'Getting started', link: '/getting-started' }
26
+ ]
27
+ },
28
+ {
29
+ text: 'Guides',
30
+ items: [
31
+ { text: 'How to customize Trek', link: '/customize' }
32
+ ]
33
+ },
34
+ {
35
+ text: 'Reference',
36
+ items: [
37
+ { text: 'Reference manual', link: '/reference/' }
38
+ ]
39
+ }
40
+ ],
41
+
42
+ '/reference/': [
43
+ { text: 'Overview', link: '/reference/' },
44
+ {
45
+ text: 'Generators',
46
+ collapsed: false,
47
+ items: [
48
+ { text: 'Installer', link: '/reference/generators/install' },
49
+ { text: 'Admin user', link: '/reference/generators/admin-user' },
50
+ { text: 'Scaffold', link: '/reference/generators/scaffold' },
51
+ { text: 'Taxonomies', link: '/reference/generators/taxonomies' }
52
+ ]
53
+ },
54
+ {
55
+ text: 'Models',
56
+ collapsed: false,
57
+ items: [
58
+ { text: 'Page', link: '/reference/models/page' },
59
+ { text: 'PageVersion', link: '/reference/models/page-version' },
60
+ { text: 'PagePath', link: '/reference/models/page-path' },
61
+ { text: 'Fragment', link: '/reference/models/fragment' },
62
+ { text: 'MenuNode', link: '/reference/models/menu-node' },
63
+ { text: 'ExternalLink', link: '/reference/models/external-link' },
64
+ { text: 'User', link: '/reference/models/user' },
65
+ { text: 'Tag & taxonomy', link: '/reference/models/tag' },
66
+ { text: 'Current', link: '/reference/models/current' }
67
+ ]
68
+ },
69
+ {
70
+ text: 'Concerns',
71
+ collapsed: false,
72
+ items: [
73
+ { text: 'Translatable', link: '/reference/concerns/translatable' },
74
+ { text: 'Contentable', link: '/reference/concerns/contentable' },
75
+ { text: 'Formattable', link: '/reference/concerns/formattable' },
76
+ { text: 'Fragmentable', link: '/reference/concerns/fragmentable' },
77
+ { text: 'Pageable', link: '/reference/concerns/pageable' },
78
+ { text: 'Sluggable', link: '/reference/concerns/sluggable' },
79
+ { text: 'Pathable', link: '/reference/concerns/pathable' },
80
+ { text: 'SearchEngineOptimizable', link: '/reference/concerns/search-engine-optimizable' },
81
+ { text: 'Versionable', link: '/reference/concerns/versionable' },
82
+ { text: 'Sectionable', link: '/reference/concerns/sectionable' },
83
+ { text: 'Orderable', link: '/reference/concerns/orderable' },
84
+ { text: 'Keyable', link: '/reference/concerns/keyable' },
85
+ { text: 'Searchable', link: '/reference/concerns/searchable' },
86
+ { text: 'Taggable', link: '/reference/concerns/taggable' },
87
+ { text: 'Phonable', link: '/reference/concerns/phonable' }
88
+ ]
89
+ },
90
+ {
91
+ text: 'Back-office',
92
+ collapsed: false,
93
+ items: [
94
+ { text: 'Controllers', link: '/reference/controllers' },
95
+ { text: 'Forms', link: '/reference/forms' },
96
+ { text: 'Formatters', link: '/reference/formatters' },
97
+ { text: 'Policies', link: '/reference/policies' },
98
+ { text: 'Uploaders', link: '/reference/uploaders' }
99
+ ]
100
+ },
101
+ {
102
+ text: 'Front-end',
103
+ collapsed: false,
104
+ items: [
105
+ { text: 'Components', link: '/reference/components' },
106
+ { text: 'Icons', link: '/reference/icons' }
107
+ ]
108
+ },
109
+ {
110
+ text: 'Configuration',
111
+ collapsed: false,
112
+ items: [
113
+ { text: 'Environment variables', link: '/reference/environment-variables' }
114
+ ]
115
+ }
116
+ ]
117
+ },
118
+
119
+ search: {
120
+ provider: 'local'
121
+ },
122
+
123
+ socialLinks: [
124
+ { icon: { svg: "<svg height='800' preserveAspectRatio='xMidYMid' viewBox='-18.5 0 293 293' width='800' xmlns='http://www.w3.org/2000/svg'><path d='m76.7478977 97.4337652-.1626607-.1626607-36.1106776 36.1106775 87.6741226 87.511462 36.110678-35.948017 51.563445-51.563445-36.110678-36.1106775v-.1626607h-103.12689z'/><path d='m127.823361.97596426-127.6886576 73.19731944v146.3946393l127.6886576 73.197319 127.688657-73.197319v-146.3946393zm103.28955 205.60313774-103.28955 59.533819-103.2895511-59.533819v-118.7423187l103.2895511-59.5338198 103.28955 59.5338198z'/></svg>" }, link: 'https://rubygems.org/gems/trek' },
125
+ { icon: 'npm', link: 'https://www.npmjs.com/package/trek' }
126
+ ],
127
+
128
+ footer: {
129
+ message: 'Released under the MIT License.',
130
+ copyright: 'Copyright © Etamin Studio'
131
+ }
132
+ }
133
+ })
@@ -0,0 +1,17 @@
1
+ // https://vitepress.dev/guide/custom-theme
2
+ import { h } from 'vue'
3
+ import DefaultTheme from 'vitepress/theme'
4
+ import './style.css'
5
+
6
+ /** @type {import('vitepress').Theme} */
7
+ export default {
8
+ extends: DefaultTheme,
9
+ Layout: () => {
10
+ return h(DefaultTheme.Layout, null, {
11
+ // https://vitepress.dev/guide/extending-default-theme#layout-slots
12
+ })
13
+ },
14
+ enhanceApp({ app, router, siteData }) {
15
+ // ...
16
+ }
17
+ }
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Customize default theme styling by overriding CSS variables:
3
+ * https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css
4
+ */
5
+
6
+ /**
7
+ * Colors
8
+ *
9
+ * Each colors have exact same color scale system with 3 levels of solid
10
+ * colors with different brightness, and 1 soft color.
11
+ *
12
+ * - `XXX-1`: The most solid color used mainly for colored text. It must
13
+ * satisfy the contrast ratio against when used on top of `XXX-soft`.
14
+ *
15
+ * - `XXX-2`: The color used mainly for hover state of the button.
16
+ *
17
+ * - `XXX-3`: The color for solid background, such as bg color of the button.
18
+ * It must satisfy the contrast ratio with pure white (#ffffff) text on
19
+ * top of it.
20
+ *
21
+ * - `XXX-soft`: The color used for subtle background such as custom container
22
+ * or badges. It must satisfy the contrast ratio when putting `XXX-1` colors
23
+ * on top of it.
24
+ *
25
+ * The soft color must be semi transparent alpha channel. This is crucial
26
+ * because it allows adding multiple "soft" colors on top of each other
27
+ * to create a accent, such as when having inline code block inside
28
+ * custom containers.
29
+ *
30
+ * - `default`: The color used purely for subtle indication without any
31
+ * special meanings attched to it such as bg color for menu hover state.
32
+ *
33
+ * - `brand`: Used for primary brand colors, such as link text, button with
34
+ * brand theme, etc.
35
+ *
36
+ * - `tip`: Used to indicate useful information. The default theme uses the
37
+ * brand color for this by default.
38
+ *
39
+ * - `warning`: Used to indicate warning to the users. Used in custom
40
+ * container, badges, etc.
41
+ *
42
+ * - `danger`: Used to show error, or dangerous message to the users. Used
43
+ * in custom container, badges, etc.
44
+ * -------------------------------------------------------------------------- */
45
+
46
+ :root {
47
+ --vp-c-default-1: var(--vp-c-gray-1);
48
+ --vp-c-default-2: var(--vp-c-gray-2);
49
+ --vp-c-default-3: var(--vp-c-gray-3);
50
+ --vp-c-default-soft: var(--vp-c-gray-soft);
51
+
52
+ --vp-c-brand-1: var(--vp-c-indigo-1);
53
+ --vp-c-brand-2: var(--vp-c-indigo-2);
54
+ --vp-c-brand-3: var(--vp-c-indigo-3);
55
+ --vp-c-brand-soft: var(--vp-c-indigo-soft);
56
+
57
+ --vp-c-tip-1: var(--vp-c-brand-1);
58
+ --vp-c-tip-2: var(--vp-c-brand-2);
59
+ --vp-c-tip-3: var(--vp-c-brand-3);
60
+ --vp-c-tip-soft: var(--vp-c-brand-soft);
61
+
62
+ --vp-c-warning-1: var(--vp-c-yellow-1);
63
+ --vp-c-warning-2: var(--vp-c-yellow-2);
64
+ --vp-c-warning-3: var(--vp-c-yellow-3);
65
+ --vp-c-warning-soft: var(--vp-c-yellow-soft);
66
+
67
+ --vp-c-danger-1: var(--vp-c-red-1);
68
+ --vp-c-danger-2: var(--vp-c-red-2);
69
+ --vp-c-danger-3: var(--vp-c-red-3);
70
+ --vp-c-danger-soft: var(--vp-c-red-soft);
71
+ }
72
+
73
+ /**
74
+ * Component: Button
75
+ * -------------------------------------------------------------------------- */
76
+
77
+ :root {
78
+ --vp-button-brand-border: transparent;
79
+ --vp-button-brand-text: var(--vp-c-white);
80
+ --vp-button-brand-bg: var(--vp-c-brand-3);
81
+ --vp-button-brand-hover-border: transparent;
82
+ --vp-button-brand-hover-text: var(--vp-c-white);
83
+ --vp-button-brand-hover-bg: var(--vp-c-brand-2);
84
+ --vp-button-brand-active-border: transparent;
85
+ --vp-button-brand-active-text: var(--vp-c-white);
86
+ --vp-button-brand-active-bg: var(--vp-c-brand-1);
87
+ }
88
+
89
+ /**
90
+ * Component: Home
91
+ * -------------------------------------------------------------------------- */
92
+
93
+ :root {
94
+ --vp-home-hero-name-color: transparent;
95
+ --vp-home-hero-name-background: -webkit-linear-gradient(
96
+ 120deg,
97
+ #bd34fe 30%,
98
+ #41d1ff
99
+ );
100
+
101
+ --vp-home-hero-image-background-image: linear-gradient(
102
+ -45deg,
103
+ #bd34fe 50%,
104
+ #47caff 50%
105
+ );
106
+ --vp-home-hero-image-filter: blur(44px);
107
+ }
108
+
109
+ @media (min-width: 640px) {
110
+ :root {
111
+ --vp-home-hero-image-filter: blur(56px);
112
+ }
113
+ }
114
+
115
+ @media (min-width: 960px) {
116
+ :root {
117
+ --vp-home-hero-image-filter: blur(68px);
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Component: Custom Block
123
+ * -------------------------------------------------------------------------- */
124
+
125
+ :root {
126
+ --vp-custom-block-tip-border: transparent;
127
+ --vp-custom-block-tip-text: var(--vp-c-text-1);
128
+ --vp-custom-block-tip-bg: var(--vp-c-brand-soft);
129
+ --vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);
130
+ }
131
+
132
+ /**
133
+ * Component: Algolia
134
+ * -------------------------------------------------------------------------- */
135
+
136
+ .DocSearch {
137
+ --docsearch-primary-color: var(--vp-c-brand-1) !important;
138
+ }
139
+
data/docs/customize.md CHANGED
@@ -1,15 +1,71 @@
1
- ## How to customize Trek
1
+ # How to customize Trek
2
2
 
3
- ### Admin panel branding
3
+ Trek is designed to get you started fast with useful conventions, then get out of the way: most of the generated code lives in your application, so customizing it is just regular Rails work. Here are the most common entry points.
4
+
5
+ ## Admin panel branding
4
6
 
5
7
  You can pick the title and subtitle used in the admin panel header.
6
8
 
7
9
  ```yml
8
10
  # config/locales/en.yml
9
- admin:
10
- brand:
11
- title: My Awesome Project
12
- subtitle: Back-office
11
+ en:
12
+ admin:
13
+ brand:
14
+ title: My Awesome Project
15
+ subtitle: Back-office
16
+ ```
17
+
18
+ ## Favicon & logo
19
+
20
+ Replace Trek's favicon with your own:
21
+
22
+ - in SVG format at `app/assets/images/favicon.svg`
23
+ - in PNG format (512 × 512 px) at `public/favicon.png`
24
+
25
+ ## Components
26
+
27
+ Trek's UI components accept options where it matters:
28
+
29
+ - **`Trek::Form::ActionsComponent`** — pick an `aspect` and add your own `classnames` to restyle form action bars.
30
+ - **`Trek::DialogComponent`** — set the `title` and the buttons of modal dialogs.
31
+ - **`Trek::Form::ContentEditorComponent`** — toggle the `nodes`, `blocks` and `floating` options to slim down the editor where full rich text isn't needed:
32
+
33
+ ```ruby
34
+ f.content_editor :intro, nodes: false, floating: false
13
35
  ```
14
36
 
15
- Place your custom icon in `app/assets/favicon.svg` to use it in place of Trek's favicon.
37
+ - **`Trek::LayoutComponent`** use the `panel` slot to add your own side panel to admin screens.
38
+
39
+ ## Models
40
+
41
+ The models generated by the installer and the scaffold are plain Active Record models in your `app/models`. Enable the commented-out hooks to opt into Trek features, for instance:
42
+
43
+ ```ruby
44
+ class Book < ApplicationRecord
45
+ include Trek::Formattable
46
+ format_attributes Trek::TypographyFormatter, :title
47
+
48
+ include Trek::Translatable
49
+ translate_attributes :title
50
+
51
+ include RecordImageUploader::Attachment(:image)
52
+ end
53
+ ```
54
+
55
+ See the [concerns reference](/reference/) for the full list.
56
+
57
+ ## Policies
58
+
59
+ Each scaffolded resource gets its own policy in `app/policies/admin`. Adjust the rules and `permitted_attributes` per role — the [policies reference](/reference/policies) shows the generated default.
60
+
61
+ ## Theming
62
+
63
+ Trek's admin supports light, dark and auto themes, selectable per user. The design tokens are based on [Radix colors](https://www.radix-ui.com/colors); override the CSS custom properties in your own stylesheet to adapt the palette.
64
+
65
+ ## Dependencies configuration
66
+
67
+ The installer configures Shrine, Postmark, Sorcery, ActionPolicy, Mobility and friends with sensible defaults — through initializers generated **in your app**. You can edit them at any time:
68
+
69
+ - `config/initializers/shrine.rb` — storage backends, upload limits
70
+ - `config/credentials.yml.enc` — Postmark API token (`EDITOR="code --wait" bin/rails credentials:edit`)
71
+ - `config/i18n-tasks.yml` — locale management rules
@@ -0,0 +1,160 @@
1
+ # Getting started
2
+
3
+ This guide takes you from an empty directory to a working Rails application with a Trek back-office.
4
+
5
+ ## Prerequisites
6
+
7
+ Make sure the following are installed:
8
+
9
+ - Ruby 3.1+
10
+ - Rails 7.0+
11
+ - PostgreSQL 12+
12
+ - Node 20+
13
+ - Yarn 3.x
14
+ - libvips
15
+
16
+ Check your Rails version:
17
+
18
+ ```sh
19
+ rails -v
20
+ ```
21
+
22
+ If it's older than 7.0, run `gem install rails` to upgrade.
23
+
24
+ Check your Yarn version:
25
+
26
+ ```sh
27
+ yarn -v
28
+ ```
29
+
30
+ If it's not a 3.x version, run:
31
+
32
+ ```sh
33
+ corepack enable
34
+ corepack install --global yarn@3
35
+ ```
36
+
37
+ ## Create your Rails project
38
+
39
+ Replace `helloworld` with your own project name:
40
+
41
+ ```sh
42
+ export TREK_PROJECT_NAME=helloworld
43
+ rails new $TREK_PROJECT_NAME -j esbuild -d postgresql \
44
+ --skip-action-mailbox --skip-action-text --skip-action-cable \
45
+ --skip-active-storage --skip-jbuilder --skip-test --skip-system-test
46
+ cd $TREK_PROJECT_NAME
47
+ ```
48
+
49
+ ## Get access to Trek
50
+
51
+ Trek is distributed as a gem and an NPM package from Etamin Studio's GitLab. [Create a deploy token](https://git.etaminstud.io/etaminstudio/trek/-/settings/repository#js-deploy-tokens) associated to the Trek project:
52
+
53
+ - **Name**: your project name (e.g. `helloworld`)
54
+ - **Username**: your project name (e.g. `helloworld`)
55
+ - **Scopes**: `read_repository`, `read_package_registry`
56
+
57
+ Export the generated token (replace `XXXXXXXXXXX`):
58
+
59
+ ```sh
60
+ export TREK_DEPLOY_TOKEN=XXXXXXXXXXX
61
+ ```
62
+
63
+ ## Install the gem
64
+
65
+ Add the deploy token to your project's local Bundler config:
66
+
67
+ ```sh
68
+ bundle config git.etaminstud.io $TREK_PROJECT_NAME:$TREK_DEPLOY_TOKEN
69
+ ```
70
+
71
+ Install the gem and add it to your `Gemfile`:
72
+
73
+ ```sh
74
+ bundle add trek --git https://git.etaminstud.io/etaminstudio/trek.git --branch main
75
+ ```
76
+
77
+ Prepare the NPM package installation:
78
+
79
+ ```sh
80
+ export NPM_AUTH_TOKEN=$TREK_DEPLOY_TOKEN
81
+ ```
82
+
83
+ ## Run the installer
84
+
85
+ ```sh
86
+ rails g trek:install
87
+ ```
88
+
89
+ The installer will:
90
+
91
+ - install all dependencies ([see the full list](/what-is-trek#what-you-get))
92
+ - create the `User` model and include Trek's concerns
93
+ - create the `Page`, `PagePath` and `PageVersion` models and include Trek's concerns
94
+ - create the `Fragment` model and include Trek's concerns
95
+ - create the relevant policies
96
+ - generate and run the relevant migrations
97
+ - set up authentication (Sorcery), authorization (ActionPolicy), uploads (Shrine), emails (Postmark), i18n, linting, CI and more
98
+
99
+ ### Configure Postmark (optional)
100
+
101
+ If you already know your [Postmark](https://postmarkapp.com) credentials, define this ENV variable **before** running the installer so it gets injected into the credentials file automatically:
102
+
103
+ ```sh
104
+ export POSTMARK_API_TOKEN=YOUR_TOKEN
105
+ ```
106
+
107
+ You can also do it manually afterwards:
108
+
109
+ ```sh
110
+ EDITOR="code --wait" bin/rails credentials:edit
111
+ ```
112
+
113
+ ### Configure DeepL (optional)
114
+
115
+ DeepL is used to translate locale files automatically when running the scaffold generator. To enable it, define this ENV variable before running the installer:
116
+
117
+ ```sh
118
+ export DEEPL_AUTH_KEY=YOUR_TOKEN
119
+ ```
120
+
121
+ Without it, translations won't happen automatically and you will have to edit each non-English locale file by hand.
122
+
123
+ ## Create an admin user
124
+
125
+ Set `ADMIN_EMAIL` and `ADMIN_PASSWORD` in your `.env`, then run:
126
+
127
+ ```sh
128
+ rails g trek:admin:user
129
+ ```
130
+
131
+ ## Start the server
132
+
133
+ ```sh
134
+ bin/dev
135
+ ```
136
+
137
+ Open `http://localhost:3000/admin` and sign in with your admin credentials. Welcome to your back-office! 🏔
138
+
139
+ ## Scaffold your first resource
140
+
141
+ Trek's scaffold generator creates everything an admin panel needs for a model:
142
+
143
+ ```sh
144
+ rails g trek:scaffold Book title:string intro:text
145
+ ```
146
+
147
+ This generates, in a single command:
148
+
149
+ - the `Book` model and migration (calling the Rails `model` generator behind the scenes)
150
+ - the `Admin::BooksController` based on `Trek::ResourceController`
151
+ - the index, show, new, edit views and form partial
152
+ - the `Admin::BookPolicy` with role-based permissions
153
+ - the admin routes
154
+ - the locale files (auto-translated via DeepL if configured)
155
+ - a menu entry in the admin dashboard
156
+
157
+ Next steps:
158
+
159
+ - [Customize Trek](/customize) — branding, favicon, components
160
+ - [Reference manual](/reference/) — generators, models, components and more