railsmaker-core 0.0.1

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 (59) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +169 -0
  3. data/bin/railsmaker +344 -0
  4. data/lib/railsmaker/generators/app_generator.rb +157 -0
  5. data/lib/railsmaker/generators/auth_generator.rb +97 -0
  6. data/lib/railsmaker/generators/base_generator.rb +39 -0
  7. data/lib/railsmaker/generators/concerns/gsub_validation.rb +24 -0
  8. data/lib/railsmaker/generators/litestream_generator.rb +89 -0
  9. data/lib/railsmaker/generators/mailjet_generator.rb +68 -0
  10. data/lib/railsmaker/generators/opentelemetry_generator.rb +79 -0
  11. data/lib/railsmaker/generators/plausible_generator.rb +33 -0
  12. data/lib/railsmaker/generators/plausible_instrumentation_generator.rb +28 -0
  13. data/lib/railsmaker/generators/sentry_generator.rb +46 -0
  14. data/lib/railsmaker/generators/server_command_generator.rb +178 -0
  15. data/lib/railsmaker/generators/signoz_generator.rb +33 -0
  16. data/lib/railsmaker/generators/signoz_opentelemetry_generator.rb +37 -0
  17. data/lib/railsmaker/generators/templates/app/credentials.example.yml +14 -0
  18. data/lib/railsmaker/generators/templates/app/main_index.html.erb +71 -0
  19. data/lib/railsmaker/generators/templates/auth/app/controllers/omniauth_callbacks_controller.rb +18 -0
  20. data/lib/railsmaker/generators/templates/litestream/litestream.yml.erb +32 -0
  21. data/lib/railsmaker/generators/templates/opentelemetry/lograge.rb.erb +9 -0
  22. data/lib/railsmaker/generators/templates/shell_scripts/plausible.sh.erb +51 -0
  23. data/lib/railsmaker/generators/templates/shell_scripts/signoz.sh.erb +38 -0
  24. data/lib/railsmaker/generators/templates/shell_scripts/signoz_opentelemetry.sh.erb +49 -0
  25. data/lib/railsmaker/generators/templates/ui/app/assets/images/og-image.webp +0 -0
  26. data/lib/railsmaker/generators/templates/ui/app/assets/images/plausible-screenshot.png +0 -0
  27. data/lib/railsmaker/generators/templates/ui/app/assets/images/signoz-screenshot.png +0 -0
  28. data/lib/railsmaker/generators/templates/ui/app/controllers/demo_controller.rb +7 -0
  29. data/lib/railsmaker/generators/templates/ui/app/controllers/pages_controller.rb +4 -0
  30. data/lib/railsmaker/generators/templates/ui/app/helpers/seo_helper.rb +39 -0
  31. data/lib/railsmaker/generators/templates/ui/app/javascript/controllers/flash_controller.js +14 -0
  32. data/lib/railsmaker/generators/templates/ui/app/javascript/controllers/index.js +11 -0
  33. data/lib/railsmaker/generators/templates/ui/app/javascript/controllers/scroll_fade_controller.js +27 -0
  34. data/lib/railsmaker/generators/templates/ui/app/views/clearance_mailer/change_password.html.erb +8 -0
  35. data/lib/railsmaker/generators/templates/ui/app/views/clearance_mailer/change_password.text.erb +5 -0
  36. data/lib/railsmaker/generators/templates/ui/app/views/demo/analytics.html.erb +214 -0
  37. data/lib/railsmaker/generators/templates/ui/app/views/demo/index.html.erb +312 -0
  38. data/lib/railsmaker/generators/templates/ui/app/views/demo/support.html.erb +147 -0
  39. data/lib/railsmaker/generators/templates/ui/app/views/layouts/_navbar.html.erb +193 -0
  40. data/lib/railsmaker/generators/templates/ui/app/views/layouts/application.html.erb +62 -0
  41. data/lib/railsmaker/generators/templates/ui/app/views/main/index.html.erb +320 -0
  42. data/lib/railsmaker/generators/templates/ui/app/views/pages/privacy.html.erb +63 -0
  43. data/lib/railsmaker/generators/templates/ui/app/views/pages/terms.html.erb +54 -0
  44. data/lib/railsmaker/generators/templates/ui/app/views/passwords/create.html.erb +9 -0
  45. data/lib/railsmaker/generators/templates/ui/app/views/passwords/edit.html.erb +21 -0
  46. data/lib/railsmaker/generators/templates/ui/app/views/passwords/new.html.erb +26 -0
  47. data/lib/railsmaker/generators/templates/ui/app/views/sessions/new.html.erb +49 -0
  48. data/lib/railsmaker/generators/templates/ui/app/views/shared/_auth_layout.html.erb +24 -0
  49. data/lib/railsmaker/generators/templates/ui/app/views/shared/_flash.html.erb +19 -0
  50. data/lib/railsmaker/generators/templates/ui/app/views/shared/_footer.html.erb +52 -0
  51. data/lib/railsmaker/generators/templates/ui/app/views/shared/_structured_data.html.erb +20 -0
  52. data/lib/railsmaker/generators/templates/ui/app/views/users/new.html.erb +49 -0
  53. data/lib/railsmaker/generators/templates/ui/config/sitemap.rb +33 -0
  54. data/lib/railsmaker/generators/templates/ui/public/icon.png +0 -0
  55. data/lib/railsmaker/generators/templates/ui/public/icon.svg +5 -0
  56. data/lib/railsmaker/generators/templates/ui/public/robots.txt +8 -0
  57. data/lib/railsmaker/generators/ui_generator.rb +68 -0
  58. data/lib/railsmaker.rb +29 -0
  59. metadata +359 -0
@@ -0,0 +1,147 @@
1
+ <div class="container mx-auto px-4 py-8 mt-16 pb-24 md:pb-8">
2
+ <!-- Page Header -->
3
+ <div class="flex items-center gap-3 mb-8">
4
+ <div class="size-12 rounded-lg bg-primary/10 flex items-center justify-center">
5
+ <svg xmlns="http://www.w3.org/2000/svg" class="size-6 text-primary" fill="none" viewBox="0 0 24 24" stroke="currentColor">
6
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
7
+ </svg>
8
+ </div>
9
+ <div>
10
+ <h2 class="text-2xl font-bold">Support</h2>
11
+ <p class="text-base-content/60">Get help with your application</p>
12
+ </div>
13
+ </div>
14
+
15
+ <!-- Main Content -->
16
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
17
+ <div class="lg:col-span-2">
18
+ <div class="card bg-base-100 shadow-xl">
19
+ <div class="card-body">
20
+ <div class="space-y-4">
21
+ <div class="collapse collapse-plus bg-base-100">
22
+ <input type="radio" name="my-accordion-2" checked="checked" />
23
+ <div class="collapse-title text-xl font-medium">
24
+ How do I get started?
25
+ </div>
26
+ <div class="collapse-content prose">
27
+ <p>Getting started is easy! Follow these steps:</p>
28
+ <ol>
29
+ <li>Sign up for an account</li>
30
+ <li>Complete your profile setup</li>
31
+ <li>Follow our quick setup guide</li>
32
+ <li>Start building your first project</li>
33
+ </ol>
34
+ </div>
35
+ </div>
36
+ <div class="collapse collapse-plus bg-base-100">
37
+ <input type="radio" name="my-accordion-2" />
38
+ <div class="collapse-title text-xl font-medium">
39
+ What payment methods do you accept?
40
+ </div>
41
+ <div class="collapse-content prose">
42
+ <p>We accept all major payment methods including:</p>
43
+ <ul>
44
+ <li>Credit/Debit Cards (Visa, Mastercard, Amex)</li>
45
+ <li>PayPal</li>
46
+ <li>Bank Transfers (ACH)</li>
47
+ <li>Wire Transfers (for annual plans)</li>
48
+ </ul>
49
+ </div>
50
+ </div>
51
+ <div class="collapse collapse-plus bg-base-100">
52
+ <input type="radio" name="my-accordion-2" />
53
+ <div class="collapse-title text-xl font-medium">
54
+ Can I cancel my subscription?
55
+ </div>
56
+ <div class="collapse-content prose">
57
+ <p>Yes, you can cancel your subscription at any time. Here's what you need to know:</p>
58
+ <ul>
59
+ <li>No long-term contracts required</li>
60
+ <li>Cancel directly from your account settings</li>
61
+ <li>Access continues until the end of your billing period</li>
62
+ <li>Data export available after cancellation</li>
63
+ </ul>
64
+ </div>
65
+ </div>
66
+ </div>
67
+ </div>
68
+ </div>
69
+ </div>
70
+
71
+ <!-- Contact Form -->
72
+ <div class="lg:col-span-1">
73
+ <div class="card bg-base-100 shadow-xl">
74
+ <div class="card-body">
75
+ <div class="flex items-center gap-3 mb-6">
76
+ <div class="size-12 rounded-lg bg-primary/10 flex items-center justify-center">
77
+ <svg xmlns="http://www.w3.org/2000/svg" class="size-6 text-primary" fill="none" viewBox="0 0 24 24" stroke="currentColor">
78
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
79
+ </svg>
80
+ </div>
81
+ <div>
82
+ <h2 class="text-xl font-bold">Contact Support</h2>
83
+ <p class="text-sm text-base-content/60">Our team typically responds within 24 hours</p>
84
+ </div>
85
+ </div>
86
+
87
+ <form class="space-y-6">
88
+ <div class="form-control">
89
+ <label class="label">
90
+ <span class="label-text font-medium">Subject</span>
91
+ </label>
92
+ <select class="select select-bordered w-full">
93
+ <option disabled selected>Select a topic</option>
94
+ <option>Technical Issue</option>
95
+ <option>Billing Question</option>
96
+ <option>Feature Request</option>
97
+ <option>Other</option>
98
+ </select>
99
+ </div>
100
+
101
+ <div class="form-control">
102
+ <label class="label">
103
+ <span class="label-text font-medium">Priority</span>
104
+ </label>
105
+ <div class="flex gap-4">
106
+ <label class="label cursor-pointer gap-2">
107
+ <input type="radio" name="priority" class="radio radio-sm radio-primary" value="low" />
108
+ <span class="label-text">Low</span>
109
+ </label>
110
+ <label class="label cursor-pointer gap-2">
111
+ <input type="radio" name="priority" class="radio radio-sm radio-primary" value="medium" checked />
112
+ <span class="label-text">Medium</span>
113
+ </label>
114
+ <label class="label cursor-pointer gap-2">
115
+ <input type="radio" name="priority" class="radio radio-sm radio-primary" value="high" />
116
+ <span class="label-text">High</span>
117
+ </label>
118
+ </div>
119
+ </div>
120
+
121
+ <div class="form-control">
122
+ <label class="label">
123
+ <span class="label-text font-medium">Message</span>
124
+ <span class="label-text-alt text-base-content/60">Max 500 characters</span>
125
+ </label>
126
+ <textarea class="textarea textarea-lg textarea-bordered min-h-32" placeholder="Describe your issue in detail..."></textarea>
127
+ </div>
128
+
129
+ <div class="form-control">
130
+ <label class="label cursor-pointer justify-start gap-3">
131
+ <input type="checkbox" class="checkbox checkbox-primary" />
132
+ <span class="label-text">Send me a copy of this message</span>
133
+ </label>
134
+ </div>
135
+
136
+ <button class="btn btn-disabled w-full">
137
+ Send Message
138
+ <svg xmlns="http://www.w3.org/2000/svg" class="size-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
139
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3" />
140
+ </svg>
141
+ </button>
142
+ </form>
143
+ </div>
144
+ </div>
145
+ </div>
146
+ </div>
147
+ </div>
@@ -0,0 +1,193 @@
1
+ <div class="navbar bg-base-100 fixed top-0 z-[1000]">
2
+ <div class="navbar-start">
3
+ <%= link_to demo_path, class: 'flex items-center gap-2 px-2 py-1 rounded-lg group' do %>
4
+ <div class="p-2 bg-primary rounded-lg transition-all duration-300 group-hover:shadow-[0_0_20px_rgba(var(--p),0.7)] group-hover:scale-110">
5
+ <svg xmlns="http://www.w3.org/2000/svg" class="size-6 text-base-100" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
6
+ <path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
7
+ <path d="M3.3 7l8.7 5 8.7-5"></path>
8
+ <path d="M12 22V12"></path>
9
+ </svg>
10
+ </div>
11
+ <span class="font-bold">
12
+ Rails<span class="text-primary border-primary">Maker</span>
13
+ </span>
14
+ <% end %>
15
+ </div>
16
+
17
+ <div class="navbar-center hidden md:flex">
18
+ <ul class="menu menu-horizontal px-1 gap-2 z-50">
19
+ <li>
20
+ <%= link_to demo_path,
21
+ class: "#{current_page?(demo_path) ? 'active bg-base-200 font-medium' : ''} flex gap-2 items-center #{!signed_in? ? 'pointer-events-none opacity-50' : ''} relative",
22
+ data: { tooltip: signed_in? ? nil : "Please sign in first" } do %>
23
+ <svg xmlns="http://www.w3.org/2000/svg" class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
24
+ Dashboard
25
+ <% end %>
26
+ </li>
27
+ <li>
28
+ <%= link_to analytics_path,
29
+ class: "#{current_page?(analytics_path) ? 'active bg-base-200 font-medium' : ''} flex gap-2 items-center #{!signed_in? ? 'pointer-events-none opacity-50' : ''}",
30
+ data: { tooltip: signed_in? ? nil : "Please sign in first" } do %>
31
+ <svg xmlns="http://www.w3.org/2000/svg" class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 12h-4l-3 9L9 3l-3 9H2"></path></svg>
32
+ Analytics
33
+ <div class="badge badge-sm badge-primary">New</div>
34
+ <% end %>
35
+ </li>
36
+ <li>
37
+ <%= link_to support_path,
38
+ class: "#{current_page?(support_path) ? 'active bg-base-200 font-medium' : ''} flex gap-2 items-center #{!signed_in? ? 'pointer-events-none opacity-50' : ''}",
39
+ data: { tooltip: signed_in? ? nil : "Please sign in first" } do %>
40
+ <svg xmlns="http://www.w3.org/2000/svg" class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>
41
+ Support
42
+ <% end %>
43
+ </li>
44
+ </ul>
45
+ </div>
46
+
47
+ <div class="navbar-end">
48
+ <!-- Only show notifications if signed in -->
49
+ <% if signed_in? %>
50
+ <!-- Notifications Dropdown -->
51
+ <div class="dropdown dropdown-end hidden md:block">
52
+ <div tabindex="0" role="button" class="btn btn-ghost btn-circle">
53
+ <div class="indicator">
54
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" /></svg>
55
+ <span class="badge badge-xs badge-primary indicator-item"></span>
56
+ </div>
57
+ </div>
58
+ <ul tabindex="0" class="dropdown-content menu menu-sm z-[1] p-2 shadow-xl bg-base-100 rounded-box w-80 mt-4">
59
+ <li class="menu-title px-4 py-2">
60
+ <span class="font-medium">Notifications</span>
61
+ </li>
62
+ <div class="px-4">
63
+ <div class="divide-y">
64
+ <div class="py-4">
65
+ <div class="flex items-center gap-4">
66
+ <div class="w-2 h-2 bg-primary rounded-full"></div>
67
+ <div>
68
+ <p class="font-medium">New feature available</p>
69
+ <p class="text-sm opacity-70">Check out our latest analytics dashboard</p>
70
+ <span class="text-xs opacity-50">2 hours ago</span>
71
+ </div>
72
+ </div>
73
+ </div>
74
+ <div class="py-4">
75
+ <div class="flex items-center gap-4">
76
+ <div class="w-2 h-2 bg-primary rounded-full"></div>
77
+ <div>
78
+ <p class="font-medium">System Update</p>
79
+ <p class="text-sm opacity-70">Performance improvements and bug fixes</p>
80
+ <span class="text-xs opacity-50">5 hours ago</span>
81
+ </div>
82
+ </div>
83
+ </div>
84
+ </div>
85
+ <button class="btn btn-disabled btn-sm w-full mt-4">View all notifications</button>
86
+ </div>
87
+ </ul>
88
+ </div>
89
+ <% end %>
90
+
91
+ <!-- Profile/Sign In Button -->
92
+ <div class="dropdown dropdown-end ml-2">
93
+ <div tabindex="0" role="button" class="btn btn-ghost btn-circle">
94
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor">
95
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
96
+ </svg>
97
+ </div>
98
+ <ul tabindex="0" class="dropdown-content menu menu-sm z-[1] p-2 shadow-xl bg-base-100 rounded-box w-52 mt-4">
99
+ <% if signed_in? %>
100
+ <li class="menu-title px-4 py-2">
101
+ <span class="font-medium">Account</span>
102
+ </li>
103
+ <li class="menu-disabled">
104
+ <a class="flex gap-2">
105
+ <svg xmlns="http://www.w3.org/2000/svg" class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
106
+ <path d="M20 7h-3a2 2 0 0 1-2-2V2"></path>
107
+ <path d="M9 18a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h7l4 4v10a2 2 0 0 1-2 2H9z"></path>
108
+ <path d="M3 15h6"></path>
109
+ <path d="M4 18h6"></path>
110
+ </svg>
111
+ Settings
112
+ </a>
113
+ </li>
114
+ <div class="divider my-1"></div>
115
+ <li>
116
+ <%= link_to sign_out_path, class: "flex gap-2 text-error", data: { turbo_method: :delete } do %>
117
+ <svg xmlns="http://www.w3.org/2000/svg" class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
118
+ <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
119
+ <polyline points="16 17 21 12 16 7"></polyline>
120
+ <line x1="21" y1="12" x2="9" y2="12"></line>
121
+ </svg>
122
+ Sign out
123
+ <% end %>
124
+ </li>
125
+ <% else %>
126
+ <li>
127
+ <%= link_to sign_in_path, class: "flex gap-2" do %>
128
+ <svg xmlns="http://www.w3.org/2000/svg" class="size-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
129
+ <path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path>
130
+ <polyline points="10 17 15 12 10 7"></polyline>
131
+ <line x1="15" y1="12" x2="3" y2="12"></line>
132
+ </svg>
133
+ Sign in
134
+ <% end %>
135
+ </li>
136
+ <% end %>
137
+ </ul>
138
+ </div>
139
+ </div>
140
+ </div>
141
+
142
+ <%# Mobile Bottom Dock Navigation - only shown on mobile %>
143
+ <div class="md:hidden">
144
+ <div class="dock dock-md bg-base-100 fixed bottom-0 left-0 right-0 border-t border-gray-200 dark:border-gray-600 z-[1000]">
145
+ <%= link_to demo_path,
146
+ class: "#{current_page?(demo_path) ? 'dock-active' : ''} relative",
147
+ disabled: signed_in? ? nil : 'disabled',
148
+ data: { tooltip: signed_in? ? nil : "Please sign in first" } do %>
149
+ <svg class="size-[1.2em]" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
150
+ <g fill="currentColor" stroke-linejoin="miter" stroke-linecap="butt">
151
+ <rect x="3" y="3" width="18" height="18" rx="2" ry="2" fill="none" stroke="currentColor" stroke-linecap="square" stroke-miterlimit="10" stroke-width="2"></rect>
152
+ <line x1="3" y1="9" x2="21" y2="9" stroke="currentColor" stroke-miterlimit="10" stroke-width="2"></line>
153
+ </g>
154
+ </svg>
155
+ <span class="dock-label">Dashboard</span>
156
+ <% end %>
157
+
158
+ <%= link_to analytics_path,
159
+ class: "#{current_page?(analytics_path) ? 'dock-active' : ''}",
160
+ disabled: signed_in? ? nil : 'disabled',
161
+ data: { tooltip: signed_in? ? nil : "Please sign in first" } do %>
162
+ <svg xmlns="http://www.w3.org/2000/svg" class="size-[1.2em]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 12h-4l-3 9L9 3l-3 9H2"></path></svg>
163
+ <span class="dock-label">Analytics</span>
164
+ <% end %>
165
+
166
+ <%= link_to support_path,
167
+ class: "#{current_page?(support_path) ? 'dock-active' : ''}",
168
+ disabled: signed_in? ? nil : 'disabled',
169
+ data: { tooltip: signed_in? ? nil : "Please sign in first" } do %>
170
+ <svg xmlns="http://www.w3.org/2000/svg" class="size-[1.2em]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg>
171
+ <span class="dock-label">Support</span>
172
+ <% end %>
173
+
174
+ <% if signed_in? %>
175
+ <%= link_to sign_out_path, data: { turbo_method: :delete } do %>
176
+ <svg xmlns="http://www.w3.org/2000/svg" class="size-[1.2em]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
177
+ <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
178
+ <polyline points="16 17 21 12 16 7"></polyline>
179
+ <line x1="21" y1="12" x2="9" y2="12"></line>
180
+ </svg>
181
+ <span class="dock-label">Sign out</span>
182
+ <% end %>
183
+ <% else %>
184
+ <%= link_to sign_in_path do %>
185
+ <svg xmlns="http://www.w3.org/2000/svg" class="size-[1.2em]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
186
+ <path d="M15 7h3a5 5 0 0 1 0 10h-3"></path>
187
+ <path d="M6 10a2 2 0 1 1-2-2V6a2 2 0 1 1 2-2h3a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2H6z"></path>
188
+ </svg>
189
+ <span class="dock-label">Sign in</span>
190
+ <% end %>
191
+ <% end %>
192
+ </div>
193
+ </div>
@@ -0,0 +1,62 @@
1
+ <!DOCTYPE html>
2
+ <html data-theme="cupcake" lang="en">
3
+ <head>
4
+ <title><%%= meta_title %></title>
5
+ <meta charset="utf-8">
6
+ <meta name="viewport" content="width=device-width,initial-scale=1">
7
+ <meta name="description" content="<%%= meta_description %>">
8
+
9
+ <!-- Open Graph / Facebook -->
10
+ <meta property="og:type" content="<%%= meta_tags[:type] %>">
11
+ <meta property="og:url" content="<%%= meta_tags[:canonical] %>">
12
+ <meta property="og:title" content="<%%= meta_tags[:title] %>">
13
+ <meta property="og:description" content="<%%= meta_tags[:description] %>">
14
+ <meta property="og:image" content="<%%= meta_tags[:image] %>">
15
+
16
+ <!-- Twitter -->
17
+ <meta name="twitter:card" content="summary_large_image">
18
+ <meta name="twitter:url" content="<%%= meta_tags[:canonical] %>">
19
+ <meta name="twitter:title" content="<%%= meta_tags[:title] %>">
20
+ <meta name="twitter:description" content="<%%= meta_tags[:description] %>">
21
+ <meta name="twitter:image" content="<%%= meta_tags[:image] %>">
22
+
23
+ <!-- Additional SEO -->
24
+ <meta name="author" content="<%%= meta_tags[:author] %>">
25
+ <meta name="robots" content="<%%= meta_tags[:robots] %>">
26
+ <link rel="canonical" href="<%%= meta_tags[:canonical] %>">
27
+
28
+ <%%= csrf_meta_tags %>
29
+ <%%= csp_meta_tag %>
30
+
31
+ <%%= yield :head %>
32
+
33
+ <%# Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!) %>
34
+ <%#= tag.link rel: "manifest", href: pwa_manifest_path(format: :json) %>
35
+
36
+ <link rel="icon" href="/icon.png" type="image/png">
37
+ <link rel="icon" href="/icon.svg" type="image/svg+xml">
38
+ <link rel="apple-touch-icon" href="/icon.png">
39
+
40
+ <%# Includes all stylesheet files in app/assets/stylesheets %>
41
+ <%%= stylesheet_link_tag :app, "data-turbo-track": "reload" %>
42
+ <%%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>
43
+ <% if plausible_enabled %>
44
+ <%%# Plausible Analytics %>
45
+ <script defer data-domain="example.com" src="https://analytics.example.com/js/script.file-downloads.outbound-links.pageview-props.revenue.tagged-events.js"></script>
46
+ <script>window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }</script>
47
+ <% end %>
48
+ <% if sentry_enabled %>
49
+ <%%= Sentry.get_trace_propagation_meta.html_safe if defined?(Sentry) %>
50
+ <% end %>
51
+ </head>
52
+
53
+ <body class="min-h-screen bg-base-200 flex flex-col">
54
+ <%%= render "layouts/navbar" unless current_page?(root_path) %>
55
+ <main class="flex-1 flex flex-col">
56
+ <%%= render "shared/flash" %>
57
+ <%%= yield %>
58
+ <%%= render "shared/footer" %>
59
+ </main>
60
+ <%%= render 'shared/structured_data' %>
61
+ </body>
62
+ </html>