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,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
|
-
|
|
1
|
+
# How to customize Trek
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
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
|
data/docs/index.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
# https://vitepress.dev/reference/default-theme-home-page
|
|
3
|
+
layout: home
|
|
4
|
+
|
|
5
|
+
hero:
|
|
6
|
+
name: "Trek"
|
|
7
|
+
text: "Take the easy path"
|
|
8
|
+
tagline: "A modern content management & back-office system for Ruby on Rails"
|
|
9
|
+
image:
|
|
10
|
+
src: /logo.svg
|
|
11
|
+
alt: Trek
|
|
12
|
+
actions:
|
|
13
|
+
- theme: brand
|
|
14
|
+
text: What's Trek?
|
|
15
|
+
link: /what-is-trek
|
|
16
|
+
- theme: alt
|
|
17
|
+
text: Quick start
|
|
18
|
+
link: /getting-started
|
|
19
|
+
|
|
20
|
+
features:
|
|
21
|
+
- icon: 🚀
|
|
22
|
+
title: Ready out of the box
|
|
23
|
+
details: One installer sets up authentication, authorization, file uploads, emails, i18n and a polished admin UI — with sensible conventions you can override later.
|
|
24
|
+
- icon: 📝
|
|
25
|
+
title: Modern content editing
|
|
26
|
+
details: A Tiptap-based rich text editor, hierarchical pages with versioning and SEO-friendly paths, plus reusable content fragments.
|
|
27
|
+
- icon: 🛠
|
|
28
|
+
title: Scaffold-driven development
|
|
29
|
+
details: One command generates the model, admin panel, views, policy, routes and locales for any resource — just like Rails scaffolding, but for your back-office.
|
|
30
|
+
- icon: 🌍
|
|
31
|
+
title: Multilingual by default
|
|
32
|
+
details: Content and admin UI translations powered by Mobility and i18n-tasks, with optional automatic translation via DeepL.
|
|
33
|
+
- icon: 🔐
|
|
34
|
+
title: Roles & policies built in
|
|
35
|
+
details: Sorcery authentication and ActionPolicy authorization with admin, editor, user, reader and guest roles, enforced across every panel.
|
|
36
|
+
- icon: 🧩
|
|
37
|
+
title: Hotwire-native UI
|
|
38
|
+
details: ViewComponents, Stimulus and Turbo under the hood, with light & dark themes, Radix colors and a customizable design system.
|
|
39
|
+
---
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" x="0" y="0" style="enable-background:new 0 0 512 512" version="1.1" viewBox="0 0 512 512"><path d="M0 0h512v512H0z" style="fill:#6ae5ac"/><path d="M201.9 93.5v91h-91c0 50.2 40.7 91 91 91v52c0 50.2 40.7 91 91 91v-325h-91zM292.9 184.5c0 50.2 40.7 91 91 91v-91h-91z" style="fill:#2d2d2d"/><path d="M292.9 418.5v-91h91c-.1 50.2-40.8 91-91 91z" style="fill:#fff"/></svg>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Components
|
|
2
|
+
|
|
3
|
+
Trek's admin UI is built with [ViewComponent](https://viewcomponent.org), [Stimulus](https://stimulus.hotwired.dev) and [Turbo](https://turbo.hotwired.dev), styled with PostCSS and [Radix colors](https://www.radix-ui.com/colors), with light & dark themes.
|
|
4
|
+
|
|
5
|
+
## UI components
|
|
6
|
+
|
|
7
|
+
The main building blocks, all in the `Trek::` namespace:
|
|
8
|
+
|
|
9
|
+
| Component | Purpose |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| `LayoutComponent` | admin layout, with header, menu and panel slots |
|
|
12
|
+
| `HeaderComponent` | top navigation bar |
|
|
13
|
+
| `MenuComponent` | sidebar navigation, with polymorphic slots |
|
|
14
|
+
| `BrandComponent` | logo, title & subtitle area |
|
|
15
|
+
| `DialogComponent` | modal dialogs, with configurable title and buttons |
|
|
16
|
+
| `TabsComponent` | tabbed interfaces |
|
|
17
|
+
| `ButtonComponent` | buttons & button-styled links |
|
|
18
|
+
| `ListComponent` | record lists |
|
|
19
|
+
| `PropertiesComponent` | key-value property display |
|
|
20
|
+
| `PaginationComponent` | Kaminari-backed pagination |
|
|
21
|
+
| `ToasterComponent` / `ToastComponent` | flash notifications |
|
|
22
|
+
| `HeadingComponent` | headings |
|
|
23
|
+
| `GateComponent` | authorization-based visibility gate |
|
|
24
|
+
| `IconComponent` | SVG [icon](/reference/icons) renderer |
|
|
25
|
+
|
|
26
|
+
## Form components
|
|
27
|
+
|
|
28
|
+
Rendered by the [form builder](/reference/forms) helpers, under `Trek::Form::`:
|
|
29
|
+
|
|
30
|
+
`GroupComponent`, `FieldsetComponent`, `ActionsComponent` (configurable aspect & classnames), `ErrorsComponent`, `TextFieldComponent`, `ImageFieldComponent`, `SoundFieldComponent`, `SwitchBoxComponent`, `CollectionSelectComponent`, `GroupedCollectionSelectComponent`, `LinkSelectComponent` and `ContentEditorComponent`.
|
|
31
|
+
|
|
32
|
+
## Content editor
|
|
33
|
+
|
|
34
|
+
`Trek::Form::ContentEditorComponent` wraps the [Tiptap](https://tiptap.dev) editor and accepts three options — `nodes`, `blocks` and `floating` (all enabled by default) — to toggle the node toolbar, block formatting and floating menu:
|
|
35
|
+
|
|
36
|
+
```ruby
|
|
37
|
+
f.content_editor :intro, nodes: false, floating: false
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Content is stored as ProseMirror JSON and rendered with [`formatted_content`](/reference/concerns/contentable). Image uploads (Uppy), link insertion and prompts are served by the [panel controllers](/reference/controllers).
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Trek::Contentable
|
|
2
|
+
|
|
3
|
+
Utilities for rich text stored as ProseMirror JSON in a `content` column — the format produced by Trek's [content editor](/reference/components#content-editor).
|
|
4
|
+
|
|
5
|
+
## Methods
|
|
6
|
+
|
|
7
|
+
| Method | Returns |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| `parsed_content` | the content as a hash (parsing JSON strings if needed) |
|
|
10
|
+
| `formatted_content` | safe HTML, rendered through the [ProseMirror pipeline](/reference/formatters) |
|
|
11
|
+
| `content_text` | plain text extracted from all text nodes |
|
|
12
|
+
| `prosemirror_content?` | whether `content` is a valid ProseMirror document |
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
class Page < ApplicationRecord
|
|
18
|
+
include Trek::Contentable
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
page.formatted_content # => "<p>Hello <strong>world</strong></p>"
|
|
22
|
+
page.content_text # => "Hello world"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Requirements
|
|
26
|
+
|
|
27
|
+
- A `content` jsonb column
|
|
28
|
+
- Used by [Page](/reference/models/page), [PageVersion](/reference/models/page-version) and [Fragment](/reference/models/fragment)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Trek::Formattable
|
|
2
|
+
|
|
3
|
+
Applies formatters to attributes before validation — out of the box, [`Trek::TypographyFormatter`](/reference/formatters#typographyformatter) and its French typography rules.
|
|
4
|
+
|
|
5
|
+
## API
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
class Page < ApplicationRecord
|
|
9
|
+
include Trek::Formattable
|
|
10
|
+
format_attributes Trek::TypographyFormatter, :title, :description
|
|
11
|
+
end
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`format_attributes(formatter_class, *attr_names)` registers the attributes; a `before_validation` callback runs the formatter on each of them.
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
page = Page.new(title: "Un titre: voici...")
|
|
20
|
+
page.valid?
|
|
21
|
+
page.title # => "Un titre : voici…"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Works on plain strings **and** on ProseMirror documents (only `text` nodes are touched; the structure is preserved).
|