rails_map 1.1.1 → 1.3.0
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/.vscode/settings.json +2 -0
- data/AUTHENTICATION.md +10 -6
- data/CHANGELOG.md +29 -3
- data/CODE_OF_CONDUCT.md +129 -0
- data/CONTRIBUTING.md +211 -0
- data/QUICKSTART.md +18 -5
- data/README.md +16 -10
- data/RELEASE_QUICK_REFERENCE.md +114 -0
- data/RELEASE_SCRIPT_GUIDE.md +405 -0
- data/RUBYGEMS_IMPROVEMENTS.md +297 -0
- data/SECURITY.md +162 -0
- data/URL_CHANGE_SUMMARY.md +150 -0
- data/config/initializers/rails_map.example.rb +1 -1
- data/docs/index.html +1564 -1275
- data/lib/generators/rails_map/install_generator.rb +4 -7
- data/lib/generators/rails_map/templates/README +15 -13
- data/lib/generators/rails_map/templates/initializer.rb +2 -2
- data/lib/generators/rails_map/templates/migration.rb +1 -1
- data/lib/rails_map/configuration.rb +8 -3
- data/lib/rails_map/parsers/model_parser.rb +1 -1
- data/lib/rails_map/version.rb +1 -1
- data/rails-map-gem.png +0 -0
- data/release.sh +338 -0
- data/templates/controller.html.erb +34 -13
- data/templates/layout.html.erb +1 -1
- metadata +47 -6
data/docs/index.html
CHANGED
|
@@ -1,1354 +1,1643 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
font-weight: 900;
|
|
188
|
-
line-height: 1.1;
|
|
189
|
-
margin-bottom: 1.5rem;
|
|
190
|
-
letter-spacing: -0.03em;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
.highlight { color: var(--ruby); }
|
|
194
|
-
.highlight-blue { color: var(--accent); }
|
|
195
|
-
|
|
196
|
-
.hero-description {
|
|
197
|
-
font-size: 1.25rem;
|
|
198
|
-
color: var(--text-muted);
|
|
199
|
-
margin-bottom: 2rem;
|
|
200
|
-
line-height: 1.7;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
.hero-buttons {
|
|
204
|
-
display: flex;
|
|
205
|
-
gap: 1rem;
|
|
206
|
-
flex-wrap: wrap;
|
|
207
|
-
margin-bottom: 3rem;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
.btn {
|
|
211
|
-
display: inline-flex;
|
|
212
|
-
align-items: center;
|
|
213
|
-
gap: 0.5rem;
|
|
214
|
-
padding: 1rem 2rem;
|
|
215
|
-
border-radius: 0.75rem;
|
|
216
|
-
font-size: 1rem;
|
|
217
|
-
font-weight: 600;
|
|
218
|
-
text-decoration: none;
|
|
219
|
-
transition: all 0.2s;
|
|
220
|
-
cursor: pointer;
|
|
221
|
-
border: none;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
.btn-primary {
|
|
225
|
-
background: linear-gradient(135deg, var(--ruby), var(--primary));
|
|
226
|
-
color: white;
|
|
227
|
-
box-shadow: 0 4px 20px rgba(204, 52, 45, 0.4);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
.btn-primary:hover {
|
|
231
|
-
transform: translateY(-2px);
|
|
232
|
-
box-shadow: 0 8px 30px rgba(204, 52, 45, 0.5);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
.btn-secondary {
|
|
236
|
-
background: var(--bg-card);
|
|
237
|
-
color: var(--text);
|
|
238
|
-
border: 1px solid var(--border);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
.btn-secondary:hover {
|
|
242
|
-
background: var(--bg-card-hover);
|
|
243
|
-
border-color: var(--border-light);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
.hero-stats {
|
|
247
|
-
display: flex;
|
|
248
|
-
gap: 2rem;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
.hero-stat {
|
|
252
|
-
text-align: left;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
.hero-stat-value {
|
|
256
|
-
font-size: 1.5rem;
|
|
257
|
-
font-weight: 800;
|
|
258
|
-
color: var(--text);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
.hero-stat-label {
|
|
262
|
-
font-size: 0.8125rem;
|
|
263
|
-
color: var(--text-dim);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/* Hero Visual */
|
|
267
|
-
.hero-visual {
|
|
268
|
-
position: relative;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
.bridge-diagram {
|
|
272
|
-
background: var(--bg-card);
|
|
273
|
-
border: 1px solid var(--border);
|
|
274
|
-
border-radius: 1.5rem;
|
|
275
|
-
padding: 2rem;
|
|
276
|
-
position: relative;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
.bridge-row {
|
|
280
|
-
display: flex;
|
|
281
|
-
align-items: center;
|
|
282
|
-
justify-content: space-between;
|
|
283
|
-
gap: 1rem;
|
|
284
|
-
margin-bottom: 1.5rem;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
.bridge-row:last-child { margin-bottom: 0; }
|
|
288
|
-
|
|
289
|
-
.bridge-box {
|
|
290
|
-
flex: 1;
|
|
291
|
-
padding: 1.25rem;
|
|
292
|
-
border-radius: 0.75rem;
|
|
293
|
-
text-align: center;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
.bridge-box.backend {
|
|
297
|
-
background: linear-gradient(135deg, rgba(204, 52, 45, 0.15), rgba(204, 52, 45, 0.05));
|
|
298
|
-
border: 1px solid rgba(204, 52, 45, 0.3);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
.bridge-box.frontend {
|
|
302
|
-
background: linear-gradient(135deg, rgba(59, 130, 246, 0.15), rgba(59, 130, 246, 0.05));
|
|
303
|
-
border: 1px solid rgba(59, 130, 246, 0.3);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
.bridge-box.center {
|
|
307
|
-
background: linear-gradient(135deg, rgba(34, 197, 94, 0.15), rgba(34, 197, 94, 0.05));
|
|
308
|
-
border: 1px solid rgba(34, 197, 94, 0.3);
|
|
309
|
-
flex: 0.8;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
.bridge-icon {
|
|
313
|
-
font-size: 2rem;
|
|
314
|
-
margin-bottom: 0.5rem;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
.bridge-label {
|
|
318
|
-
font-size: 0.75rem;
|
|
319
|
-
font-weight: 600;
|
|
320
|
-
text-transform: uppercase;
|
|
321
|
-
letter-spacing: 0.05em;
|
|
322
|
-
color: var(--text-muted);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
.bridge-title {
|
|
326
|
-
font-size: 1rem;
|
|
327
|
-
font-weight: 700;
|
|
328
|
-
margin-top: 0.25rem;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
.bridge-connector {
|
|
332
|
-
display: flex;
|
|
333
|
-
align-items: center;
|
|
334
|
-
justify-content: center;
|
|
335
|
-
color: var(--text-dim);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
.bridge-connector svg {
|
|
339
|
-
animation: flowRight 1.5s infinite;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
@keyframes flowRight {
|
|
343
|
-
0%, 100% { opacity: 0.3; transform: translateX(-5px); }
|
|
344
|
-
50% { opacity: 1; transform: translateX(5px); }
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
.bridge-items {
|
|
348
|
-
display: grid;
|
|
349
|
-
grid-template-columns: repeat(3, 1fr);
|
|
350
|
-
gap: 0.75rem;
|
|
351
|
-
margin-top: 1.5rem;
|
|
352
|
-
padding-top: 1.5rem;
|
|
353
|
-
border-top: 1px solid var(--border);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
.bridge-item {
|
|
357
|
-
background: var(--bg-dark);
|
|
358
|
-
border: 1px solid var(--border);
|
|
359
|
-
border-radius: 0.5rem;
|
|
360
|
-
padding: 0.75rem;
|
|
361
|
-
text-align: center;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
.bridge-item-icon {
|
|
365
|
-
font-size: 1.25rem;
|
|
366
|
-
margin-bottom: 0.25rem;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
.bridge-item-text {
|
|
370
|
-
font-size: 0.75rem;
|
|
371
|
-
color: var(--text-muted);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
/* Problem Section */
|
|
375
|
-
.problem {
|
|
376
|
-
padding: 6rem 2rem;
|
|
377
|
-
background: var(--bg-card);
|
|
378
|
-
border-top: 1px solid var(--border);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
.problem-content {
|
|
382
|
-
max-width: 900px;
|
|
383
|
-
margin: 0 auto;
|
|
384
|
-
text-align: center;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
.section-label {
|
|
388
|
-
display: inline-block;
|
|
389
|
-
font-size: 0.75rem;
|
|
390
|
-
font-weight: 700;
|
|
391
|
-
text-transform: uppercase;
|
|
392
|
-
letter-spacing: 0.1em;
|
|
393
|
-
color: var(--ruby);
|
|
394
|
-
margin-bottom: 1rem;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
.section-title {
|
|
398
|
-
font-size: clamp(2rem, 4vw, 2.75rem);
|
|
399
|
-
font-weight: 800;
|
|
400
|
-
margin-bottom: 1.5rem;
|
|
401
|
-
letter-spacing: -0.025em;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
.section-description {
|
|
405
|
-
font-size: 1.125rem;
|
|
406
|
-
color: var(--text-muted);
|
|
407
|
-
max-width: 700px;
|
|
408
|
-
margin: 0 auto 3rem;
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
.pain-points {
|
|
412
|
-
display: grid;
|
|
413
|
-
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
414
|
-
gap: 1.5rem;
|
|
415
|
-
text-align: left;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
.pain-point {
|
|
419
|
-
background: var(--bg-dark);
|
|
420
|
-
border: 1px solid var(--border);
|
|
421
|
-
border-radius: 1rem;
|
|
422
|
-
padding: 1.5rem;
|
|
423
|
-
position: relative;
|
|
424
|
-
overflow: hidden;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
.pain-point::before {
|
|
428
|
-
content: '';
|
|
429
|
-
position: absolute;
|
|
430
|
-
top: 0;
|
|
431
|
-
left: 0;
|
|
432
|
-
right: 0;
|
|
433
|
-
height: 3px;
|
|
434
|
-
background: linear-gradient(90deg, var(--ruby), var(--primary-light));
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
.pain-point-icon {
|
|
438
|
-
font-size: 1.5rem;
|
|
439
|
-
margin-bottom: 1rem;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
.pain-point h3 {
|
|
443
|
-
font-size: 1.125rem;
|
|
444
|
-
font-weight: 700;
|
|
445
|
-
margin-bottom: 0.5rem;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
.pain-point p {
|
|
449
|
-
font-size: 0.9375rem;
|
|
450
|
-
color: var(--text-muted);
|
|
451
|
-
line-height: 1.6;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
/* Solution Section */
|
|
455
|
-
.solution {
|
|
456
|
-
padding: 6rem 2rem;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
.solution-header {
|
|
460
|
-
text-align: center;
|
|
461
|
-
margin-bottom: 4rem;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
.solution-grid {
|
|
465
|
-
display: grid;
|
|
466
|
-
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
|
467
|
-
gap: 2rem;
|
|
468
|
-
max-width: 1200px;
|
|
469
|
-
margin: 0 auto;
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
.solution-card {
|
|
473
|
-
background: var(--bg-card);
|
|
474
|
-
border: 1px solid var(--border);
|
|
475
|
-
border-radius: 1.25rem;
|
|
476
|
-
padding: 2rem;
|
|
477
|
-
transition: all 0.3s;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
.solution-card:hover {
|
|
481
|
-
border-color: var(--ruby);
|
|
482
|
-
transform: translateY(-4px);
|
|
483
|
-
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
.solution-card-icon {
|
|
487
|
-
width: 56px;
|
|
488
|
-
height: 56px;
|
|
489
|
-
background: linear-gradient(135deg, rgba(204, 52, 45, 0.2), rgba(59, 130, 246, 0.2));
|
|
490
|
-
border-radius: 1rem;
|
|
491
|
-
display: flex;
|
|
492
|
-
align-items: center;
|
|
493
|
-
justify-content: center;
|
|
494
|
-
font-size: 1.75rem;
|
|
495
|
-
margin-bottom: 1.5rem;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
.solution-card h3 {
|
|
499
|
-
font-size: 1.25rem;
|
|
500
|
-
font-weight: 700;
|
|
501
|
-
margin-bottom: 0.75rem;
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
.solution-card p {
|
|
505
|
-
font-size: 0.9375rem;
|
|
506
|
-
color: var(--text-muted);
|
|
507
|
-
line-height: 1.7;
|
|
508
|
-
margin-bottom: 1rem;
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
.solution-card-features {
|
|
512
|
-
display: flex;
|
|
513
|
-
flex-wrap: wrap;
|
|
514
|
-
gap: 0.5rem;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
.solution-card-feature {
|
|
518
|
-
font-size: 0.75rem;
|
|
519
|
-
padding: 0.25rem 0.625rem;
|
|
520
|
-
background: var(--bg-dark);
|
|
521
|
-
border: 1px solid var(--border);
|
|
522
|
-
border-radius: 1rem;
|
|
523
|
-
color: var(--text-muted);
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
/* Demo Section */
|
|
527
|
-
.demo {
|
|
528
|
-
padding: 6rem 2rem;
|
|
529
|
-
background: var(--bg-card);
|
|
530
|
-
border-top: 1px solid var(--border);
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
.demo-header {
|
|
534
|
-
text-align: center;
|
|
535
|
-
margin-bottom: 3rem;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
.demo-container {
|
|
539
|
-
max-width: 1000px;
|
|
540
|
-
margin: 0 auto;
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
.demo-window {
|
|
544
|
-
background: linear-gradient(135deg, var(--ruby), var(--accent));
|
|
545
|
-
padding: 3px;
|
|
546
|
-
border-radius: 1rem;
|
|
547
|
-
box-shadow: 0 25px 80px rgba(204, 52, 45, 0.2), 0 10px 30px rgba(0, 0, 0, 0.3);
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
.demo-window-inner {
|
|
551
|
-
background: var(--bg-dark);
|
|
552
|
-
border-radius: calc(1rem - 3px);
|
|
553
|
-
overflow: hidden;
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
.demo-header-bar {
|
|
557
|
-
display: flex;
|
|
558
|
-
align-items: center;
|
|
559
|
-
gap: 0.5rem;
|
|
560
|
-
padding: 1rem 1.25rem;
|
|
561
|
-
background: var(--bg-card);
|
|
562
|
-
border-bottom: 1px solid var(--border);
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
.demo-dot {
|
|
566
|
-
width: 12px;
|
|
567
|
-
height: 12px;
|
|
568
|
-
border-radius: 50%;
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
.demo-dot.red { background: #ff5f57; }
|
|
572
|
-
.demo-dot.yellow { background: #febc2e; }
|
|
573
|
-
.demo-dot.green { background: #28c840; }
|
|
574
|
-
|
|
575
|
-
.demo-url {
|
|
576
|
-
flex: 1;
|
|
577
|
-
text-align: center;
|
|
578
|
-
font-size: 0.8125rem;
|
|
579
|
-
color: var(--text-dim);
|
|
580
|
-
font-family: 'JetBrains Mono', monospace;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
.demo-content {
|
|
584
|
-
padding: 2rem;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
.demo-nav {
|
|
588
|
-
display: flex;
|
|
589
|
-
gap: 1rem;
|
|
590
|
-
margin-bottom: 2rem;
|
|
591
|
-
padding-bottom: 1rem;
|
|
592
|
-
border-bottom: 1px solid var(--border);
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
.demo-nav-item {
|
|
596
|
-
padding: 0.5rem 1rem;
|
|
597
|
-
background: var(--bg-card);
|
|
598
|
-
border: 1px solid var(--border);
|
|
599
|
-
border-radius: 0.5rem;
|
|
600
|
-
font-size: 0.875rem;
|
|
601
|
-
color: var(--text-muted);
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
.demo-nav-item.active {
|
|
605
|
-
background: var(--ruby);
|
|
606
|
-
border-color: var(--ruby);
|
|
607
|
-
color: white;
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
.demo-stats {
|
|
611
|
-
display: grid;
|
|
612
|
-
grid-template-columns: repeat(3, 1fr);
|
|
613
|
-
gap: 1rem;
|
|
614
|
-
margin-bottom: 2rem;
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
.demo-stat {
|
|
618
|
-
background: var(--bg-card);
|
|
619
|
-
border: 1px solid var(--border);
|
|
620
|
-
border-radius: 0.75rem;
|
|
621
|
-
padding: 1.5rem;
|
|
622
|
-
text-align: center;
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
.demo-stat-value {
|
|
626
|
-
font-size: 2.5rem;
|
|
627
|
-
font-weight: 800;
|
|
628
|
-
background: linear-gradient(135deg, var(--ruby), var(--accent));
|
|
629
|
-
-webkit-background-clip: text;
|
|
630
|
-
-webkit-text-fill-color: transparent;
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
.demo-stat-label {
|
|
634
|
-
font-size: 0.75rem;
|
|
635
|
-
color: var(--text-dim);
|
|
636
|
-
text-transform: uppercase;
|
|
637
|
-
letter-spacing: 0.05em;
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
.demo-cards {
|
|
641
|
-
display: grid;
|
|
642
|
-
grid-template-columns: repeat(2, 1fr);
|
|
643
|
-
gap: 1rem;
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
.demo-card {
|
|
647
|
-
background: var(--bg-card);
|
|
648
|
-
border: 1px solid var(--border);
|
|
649
|
-
border-radius: 0.75rem;
|
|
650
|
-
padding: 1.25rem;
|
|
651
|
-
transition: all 0.2s;
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
.demo-card:hover {
|
|
655
|
-
border-color: var(--border-light);
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
.demo-card-header {
|
|
659
|
-
display: flex;
|
|
660
|
-
justify-content: space-between;
|
|
661
|
-
align-items: center;
|
|
662
|
-
margin-bottom: 0.75rem;
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
.demo-card-title {
|
|
666
|
-
font-weight: 600;
|
|
667
|
-
font-size: 0.9375rem;
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
.demo-card-badge {
|
|
671
|
-
font-size: 0.6875rem;
|
|
672
|
-
padding: 0.25rem 0.5rem;
|
|
673
|
-
background: rgba(34, 197, 94, 0.15);
|
|
674
|
-
color: var(--success);
|
|
675
|
-
border-radius: 0.25rem;
|
|
676
|
-
font-weight: 600;
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
.demo-card-meta {
|
|
680
|
-
font-size: 0.8125rem;
|
|
681
|
-
color: var(--text-dim);
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
/* How it Works */
|
|
685
|
-
.how-it-works {
|
|
686
|
-
padding: 6rem 2rem;
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
.how-header {
|
|
690
|
-
text-align: center;
|
|
691
|
-
margin-bottom: 4rem;
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
.steps {
|
|
695
|
-
max-width: 800px;
|
|
696
|
-
margin: 0 auto;
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
.step {
|
|
700
|
-
display: flex;
|
|
701
|
-
gap: 2rem;
|
|
702
|
-
margin-bottom: 3rem;
|
|
703
|
-
position: relative;
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
.step:not(:last-child)::after {
|
|
707
|
-
content: '';
|
|
708
|
-
position: absolute;
|
|
709
|
-
left: 28px;
|
|
710
|
-
top: 60px;
|
|
711
|
-
bottom: -30px;
|
|
712
|
-
width: 2px;
|
|
713
|
-
background: linear-gradient(to bottom, var(--ruby), transparent);
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
.step-number {
|
|
717
|
-
width: 56px;
|
|
718
|
-
height: 56px;
|
|
719
|
-
min-width: 56px;
|
|
720
|
-
background: linear-gradient(135deg, var(--ruby), var(--primary));
|
|
721
|
-
border-radius: 50%;
|
|
722
|
-
display: flex;
|
|
723
|
-
align-items: center;
|
|
724
|
-
justify-content: center;
|
|
725
|
-
font-weight: 800;
|
|
726
|
-
font-size: 1.25rem;
|
|
727
|
-
color: white;
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
.step-content {
|
|
731
|
-
flex: 1;
|
|
732
|
-
padding-top: 0.5rem;
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
.step-content h3 {
|
|
736
|
-
font-size: 1.375rem;
|
|
737
|
-
font-weight: 700;
|
|
738
|
-
margin-bottom: 0.5rem;
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
.step-content p {
|
|
742
|
-
color: var(--text-muted);
|
|
743
|
-
margin-bottom: 1rem;
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
.step-code {
|
|
747
|
-
background: var(--bg-card);
|
|
748
|
-
border: 1px solid var(--border);
|
|
749
|
-
border-radius: 0.75rem;
|
|
750
|
-
padding: 1.25rem;
|
|
751
|
-
font-family: 'JetBrains Mono', monospace;
|
|
752
|
-
font-size: 0.875rem;
|
|
753
|
-
overflow-x: auto;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
.step-code .comment { color: var(--text-dim); }
|
|
757
|
-
.step-code .keyword { color: #f472b6; }
|
|
758
|
-
.step-code .string { color: #4ade80; }
|
|
759
|
-
|
|
760
|
-
/* CTA */
|
|
761
|
-
.cta {
|
|
762
|
-
padding: 8rem 2rem;
|
|
763
|
-
text-align: center;
|
|
764
|
-
background: var(--bg-card);
|
|
765
|
-
border-top: 1px solid var(--border);
|
|
766
|
-
position: relative;
|
|
767
|
-
overflow: hidden;
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
.cta::before {
|
|
771
|
-
content: '';
|
|
772
|
-
position: absolute;
|
|
773
|
-
top: 50%;
|
|
774
|
-
left: 50%;
|
|
775
|
-
transform: translate(-50%, -50%);
|
|
776
|
-
width: 800px;
|
|
777
|
-
height: 800px;
|
|
778
|
-
background: radial-gradient(ellipse at center, rgba(204, 52, 45, 0.1) 0%, transparent 60%);
|
|
779
|
-
pointer-events: none;
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
.cta-content {
|
|
783
|
-
max-width: 700px;
|
|
784
|
-
margin: 0 auto;
|
|
785
|
-
position: relative;
|
|
786
|
-
z-index: 1;
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
.cta h2 {
|
|
790
|
-
font-size: clamp(2rem, 4vw, 3rem);
|
|
791
|
-
font-weight: 800;
|
|
792
|
-
margin-bottom: 1rem;
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
.cta p {
|
|
796
|
-
font-size: 1.25rem;
|
|
797
|
-
color: var(--text-muted);
|
|
798
|
-
margin-bottom: 2rem;
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
.cta-buttons {
|
|
802
|
-
display: flex;
|
|
803
|
-
gap: 1rem;
|
|
804
|
-
justify-content: center;
|
|
805
|
-
flex-wrap: wrap;
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
.install-box {
|
|
809
|
-
display: inline-flex;
|
|
810
|
-
align-items: center;
|
|
811
|
-
gap: 1rem;
|
|
812
|
-
background: var(--bg-dark);
|
|
813
|
-
border: 1px solid var(--border);
|
|
814
|
-
border-radius: 0.75rem;
|
|
815
|
-
padding: 1rem 1.5rem;
|
|
816
|
-
font-family: 'JetBrains Mono', monospace;
|
|
817
|
-
font-size: 0.9375rem;
|
|
818
|
-
margin-top: 2rem;
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
.install-box code { color: var(--ruby-light); }
|
|
822
|
-
|
|
823
|
-
.copy-btn {
|
|
824
|
-
background: none;
|
|
825
|
-
border: none;
|
|
826
|
-
color: var(--text-muted);
|
|
827
|
-
cursor: pointer;
|
|
828
|
-
padding: 0.5rem;
|
|
829
|
-
border-radius: 0.375rem;
|
|
830
|
-
transition: all 0.2s;
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
.copy-btn:hover {
|
|
834
|
-
background: var(--border);
|
|
835
|
-
color: var(--text);
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
/* Footer */
|
|
839
|
-
.footer {
|
|
840
|
-
padding: 3rem 2rem;
|
|
841
|
-
border-top: 1px solid var(--border);
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
.footer-content {
|
|
845
|
-
max-width: 1200px;
|
|
846
|
-
margin: 0 auto;
|
|
847
|
-
display: flex;
|
|
848
|
-
justify-content: space-between;
|
|
849
|
-
align-items: center;
|
|
850
|
-
flex-wrap: wrap;
|
|
851
|
-
gap: 1.5rem;
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
.footer-links {
|
|
855
|
-
display: flex;
|
|
856
|
-
gap: 2rem;
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
.footer-links a {
|
|
860
|
-
color: var(--text-muted);
|
|
861
|
-
text-decoration: none;
|
|
862
|
-
font-size: 0.875rem;
|
|
863
|
-
transition: color 0.2s;
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
.footer-links a:hover { color: var(--text); }
|
|
867
|
-
|
|
868
|
-
.footer-copy {
|
|
869
|
-
color: var(--text-dim);
|
|
870
|
-
font-size: 0.875rem;
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
.footer-copy a {
|
|
874
|
-
color: var(--ruby-light);
|
|
875
|
-
text-decoration: none;
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
.footer-copy a:hover { text-decoration: underline; }
|
|
879
|
-
|
|
880
|
-
/* Responsive */
|
|
881
|
-
@media (max-width: 968px) {
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>
|
|
7
|
+
RailsMap - The Missing Bridge Between Your Rails Backend & Frontend Team
|
|
8
|
+
</title>
|
|
9
|
+
<meta
|
|
10
|
+
name="description"
|
|
11
|
+
content="RailsMap automatically maps your Rails routes, controllers, and models into beautiful, interactive documentation. Bridge the gap between backend and frontend teams instantly."
|
|
12
|
+
/>
|
|
13
|
+
<meta
|
|
14
|
+
name="keywords"
|
|
15
|
+
content="rails, api documentation, ruby on rails, api docs, rails routes, rails models, developer tools"
|
|
16
|
+
/>
|
|
17
|
+
<meta
|
|
18
|
+
property="og:title"
|
|
19
|
+
content="RailsMap - The Missing Bridge Between Backend & Frontend"
|
|
20
|
+
/>
|
|
21
|
+
<meta
|
|
22
|
+
property="og:description"
|
|
23
|
+
content="Auto-generate interactive API documentation for Rails. Zero configuration."
|
|
24
|
+
/>
|
|
25
|
+
<meta property="og:type" content="website" />
|
|
26
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
27
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
28
|
+
<link
|
|
29
|
+
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500&display=swap"
|
|
30
|
+
rel="stylesheet"
|
|
31
|
+
/>
|
|
32
|
+
<style>
|
|
33
|
+
:root {
|
|
34
|
+
--primary: #ef4444;
|
|
35
|
+
--primary-dark: #dc2626;
|
|
36
|
+
--primary-light: #f87171;
|
|
37
|
+
--ruby: #cc342d;
|
|
38
|
+
--ruby-light: #ff6b6b;
|
|
39
|
+
--accent: #3b82f6;
|
|
40
|
+
--accent-light: #60a5fa;
|
|
41
|
+
--bg-dark: #09090b;
|
|
42
|
+
--bg-card: #18181b;
|
|
43
|
+
--bg-card-hover: #27272a;
|
|
44
|
+
--text: #fafafa;
|
|
45
|
+
--text-muted: #a1a1aa;
|
|
46
|
+
--text-dim: #71717a;
|
|
47
|
+
--border: #27272a;
|
|
48
|
+
--border-light: #3f3f46;
|
|
49
|
+
--success: #22c55e;
|
|
50
|
+
--warning: #f59e0b;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
* {
|
|
54
|
+
margin: 0;
|
|
55
|
+
padding: 0;
|
|
56
|
+
box-sizing: border-box;
|
|
57
|
+
}
|
|
58
|
+
html {
|
|
59
|
+
scroll-behavior: smooth;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
body {
|
|
63
|
+
font-family:
|
|
64
|
+
"Inter",
|
|
65
|
+
-apple-system,
|
|
66
|
+
BlinkMacSystemFont,
|
|
67
|
+
sans-serif;
|
|
68
|
+
background: var(--bg-dark);
|
|
69
|
+
color: var(--text);
|
|
70
|
+
line-height: 1.6;
|
|
71
|
+
overflow-x: hidden;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.container {
|
|
75
|
+
max-width: 1200px;
|
|
76
|
+
margin: 0 auto;
|
|
77
|
+
padding: 0 2rem;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* Navbar */
|
|
81
|
+
.navbar {
|
|
82
|
+
position: fixed;
|
|
83
|
+
top: 0;
|
|
84
|
+
left: 0;
|
|
85
|
+
right: 0;
|
|
86
|
+
z-index: 100;
|
|
87
|
+
padding: 1rem 2rem;
|
|
88
|
+
background: rgba(9, 9, 11, 0.9);
|
|
89
|
+
backdrop-filter: blur(20px);
|
|
90
|
+
border-bottom: 1px solid var(--border);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.navbar-content {
|
|
94
|
+
max-width: 1200px;
|
|
95
|
+
margin: 0 auto;
|
|
96
|
+
display: flex;
|
|
97
|
+
justify-content: space-between;
|
|
98
|
+
align-items: center;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.logo {
|
|
102
|
+
display: flex;
|
|
103
|
+
align-items: center;
|
|
104
|
+
gap: 0.75rem;
|
|
105
|
+
text-decoration: none;
|
|
106
|
+
color: var(--text);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.logo-img {
|
|
110
|
+
height: 40px;
|
|
111
|
+
width: auto;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.logo-text {
|
|
115
|
+
font-size: 1.5rem;
|
|
116
|
+
font-weight: 800;
|
|
117
|
+
letter-spacing: -0.025em;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.logo-text span {
|
|
121
|
+
color: var(--ruby);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.nav-links {
|
|
125
|
+
display: flex;
|
|
126
|
+
align-items: center;
|
|
127
|
+
gap: 2rem;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.nav-links a {
|
|
131
|
+
color: var(--text-muted);
|
|
132
|
+
text-decoration: none;
|
|
133
|
+
font-size: 0.9375rem;
|
|
134
|
+
font-weight: 500;
|
|
135
|
+
transition: color 0.2s;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.nav-links a:hover {
|
|
139
|
+
color: var(--text);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.nav-btn {
|
|
143
|
+
padding: 0.625rem 1.25rem;
|
|
144
|
+
background: var(--ruby);
|
|
145
|
+
color: white !important;
|
|
146
|
+
border-radius: 0.5rem;
|
|
147
|
+
font-weight: 600;
|
|
148
|
+
transition: all 0.2s;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.nav-btn:hover {
|
|
152
|
+
background: var(--ruby-light);
|
|
153
|
+
transform: translateY(-1px);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* Hero */
|
|
157
|
+
.hero {
|
|
158
|
+
min-height: 100vh;
|
|
159
|
+
display: flex;
|
|
160
|
+
align-items: center;
|
|
161
|
+
padding: 8rem 2rem 4rem;
|
|
162
|
+
position: relative;
|
|
163
|
+
overflow: hidden;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.hero::before {
|
|
167
|
+
content: "";
|
|
168
|
+
position: absolute;
|
|
169
|
+
top: -50%;
|
|
170
|
+
left: -50%;
|
|
171
|
+
width: 200%;
|
|
172
|
+
height: 200%;
|
|
173
|
+
background:
|
|
174
|
+
radial-gradient(
|
|
175
|
+
ellipse at 30% 20%,
|
|
176
|
+
rgba(204, 52, 45, 0.08) 0%,
|
|
177
|
+
transparent 50%
|
|
178
|
+
),
|
|
179
|
+
radial-gradient(
|
|
180
|
+
ellipse at 70% 80%,
|
|
181
|
+
rgba(59, 130, 246, 0.08) 0%,
|
|
182
|
+
transparent 50%
|
|
183
|
+
);
|
|
184
|
+
pointer-events: none;
|
|
185
|
+
}
|
|
186
|
+
|
|
882
187
|
.hero-content {
|
|
883
|
-
|
|
188
|
+
max-width: 1200px;
|
|
189
|
+
margin: 0 auto;
|
|
190
|
+
display: grid;
|
|
191
|
+
grid-template-columns: 1fr 1fr;
|
|
192
|
+
gap: 4rem;
|
|
193
|
+
align-items: center;
|
|
194
|
+
position: relative;
|
|
195
|
+
z-index: 1;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.hero-text {
|
|
199
|
+
max-width: 600px;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.hero-badge {
|
|
203
|
+
display: inline-flex;
|
|
204
|
+
align-items: center;
|
|
205
|
+
gap: 0.5rem;
|
|
206
|
+
padding: 0.5rem 1rem;
|
|
207
|
+
background: rgba(204, 52, 45, 0.1);
|
|
208
|
+
border: 1px solid rgba(204, 52, 45, 0.3);
|
|
209
|
+
border-radius: 2rem;
|
|
210
|
+
font-size: 0.875rem;
|
|
211
|
+
color: var(--ruby-light);
|
|
212
|
+
margin-bottom: 1.5rem;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.hero-badge-dot {
|
|
216
|
+
width: 8px;
|
|
217
|
+
height: 8px;
|
|
218
|
+
background: var(--ruby);
|
|
219
|
+
border-radius: 50%;
|
|
220
|
+
animation: pulse 2s infinite;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
@keyframes pulse {
|
|
224
|
+
0%,
|
|
225
|
+
100% {
|
|
226
|
+
opacity: 1;
|
|
227
|
+
transform: scale(1);
|
|
228
|
+
}
|
|
229
|
+
50% {
|
|
230
|
+
opacity: 0.5;
|
|
231
|
+
transform: scale(0.9);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
h1 {
|
|
236
|
+
font-size: clamp(2.5rem, 5vw, 3.5rem);
|
|
237
|
+
font-weight: 900;
|
|
238
|
+
line-height: 1.1;
|
|
239
|
+
margin-bottom: 1.5rem;
|
|
240
|
+
letter-spacing: -0.03em;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.highlight {
|
|
244
|
+
color: var(--ruby);
|
|
245
|
+
}
|
|
246
|
+
.highlight-blue {
|
|
247
|
+
color: var(--accent);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.hero-description {
|
|
251
|
+
font-size: 1.25rem;
|
|
252
|
+
color: var(--text-muted);
|
|
253
|
+
margin-bottom: 2rem;
|
|
254
|
+
line-height: 1.7;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.hero-buttons {
|
|
258
|
+
display: flex;
|
|
259
|
+
gap: 1rem;
|
|
260
|
+
flex-wrap: wrap;
|
|
261
|
+
margin-bottom: 3rem;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.btn {
|
|
265
|
+
display: inline-flex;
|
|
266
|
+
align-items: center;
|
|
267
|
+
gap: 0.5rem;
|
|
268
|
+
padding: 1rem 2rem;
|
|
269
|
+
border-radius: 0.75rem;
|
|
270
|
+
font-size: 1rem;
|
|
271
|
+
font-weight: 600;
|
|
272
|
+
text-decoration: none;
|
|
273
|
+
transition: all 0.2s;
|
|
274
|
+
cursor: pointer;
|
|
275
|
+
border: none;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.btn-primary {
|
|
279
|
+
background: linear-gradient(135deg, var(--ruby), var(--primary));
|
|
280
|
+
color: white;
|
|
281
|
+
box-shadow: 0 4px 20px rgba(204, 52, 45, 0.4);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.btn-primary:hover {
|
|
285
|
+
transform: translateY(-2px);
|
|
286
|
+
box-shadow: 0 8px 30px rgba(204, 52, 45, 0.5);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.btn-secondary {
|
|
290
|
+
background: var(--bg-card);
|
|
291
|
+
color: var(--text);
|
|
292
|
+
border: 1px solid var(--border);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.btn-secondary:hover {
|
|
296
|
+
background: var(--bg-card-hover);
|
|
297
|
+
border-color: var(--border-light);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.hero-stats {
|
|
301
|
+
display: flex;
|
|
302
|
+
gap: 2rem;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.hero-stat {
|
|
306
|
+
text-align: left;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.hero-stat-value {
|
|
310
|
+
font-size: 1.5rem;
|
|
311
|
+
font-weight: 800;
|
|
312
|
+
color: var(--text);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.hero-stat-label {
|
|
316
|
+
font-size: 0.8125rem;
|
|
317
|
+
color: var(--text-dim);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/* Hero Visual */
|
|
321
|
+
.hero-visual {
|
|
322
|
+
position: relative;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.bridge-diagram {
|
|
326
|
+
background: var(--bg-card);
|
|
327
|
+
border: 1px solid var(--border);
|
|
328
|
+
border-radius: 1.5rem;
|
|
329
|
+
padding: 2rem;
|
|
330
|
+
position: relative;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.bridge-row {
|
|
334
|
+
display: flex;
|
|
335
|
+
align-items: center;
|
|
336
|
+
justify-content: space-between;
|
|
337
|
+
gap: 1rem;
|
|
338
|
+
margin-bottom: 1.5rem;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.bridge-row:last-child {
|
|
342
|
+
margin-bottom: 0;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
.bridge-box {
|
|
346
|
+
flex: 1;
|
|
347
|
+
padding: 1.25rem;
|
|
348
|
+
border-radius: 0.75rem;
|
|
884
349
|
text-align: center;
|
|
885
350
|
}
|
|
886
351
|
|
|
887
|
-
.
|
|
352
|
+
.bridge-box.backend {
|
|
353
|
+
background: linear-gradient(
|
|
354
|
+
135deg,
|
|
355
|
+
rgba(204, 52, 45, 0.15),
|
|
356
|
+
rgba(204, 52, 45, 0.05)
|
|
357
|
+
);
|
|
358
|
+
border: 1px solid rgba(204, 52, 45, 0.3);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
.bridge-box.frontend {
|
|
362
|
+
background: linear-gradient(
|
|
363
|
+
135deg,
|
|
364
|
+
rgba(59, 130, 246, 0.15),
|
|
365
|
+
rgba(59, 130, 246, 0.05)
|
|
366
|
+
);
|
|
367
|
+
border: 1px solid rgba(59, 130, 246, 0.3);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.bridge-box.center {
|
|
371
|
+
background: linear-gradient(
|
|
372
|
+
135deg,
|
|
373
|
+
rgba(34, 197, 94, 0.15),
|
|
374
|
+
rgba(34, 197, 94, 0.05)
|
|
375
|
+
);
|
|
376
|
+
border: 1px solid rgba(34, 197, 94, 0.3);
|
|
377
|
+
flex: 0.8;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.bridge-icon {
|
|
381
|
+
font-size: 2rem;
|
|
382
|
+
margin-bottom: 0.5rem;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
.bridge-label {
|
|
386
|
+
font-size: 0.75rem;
|
|
387
|
+
font-weight: 600;
|
|
388
|
+
text-transform: uppercase;
|
|
389
|
+
letter-spacing: 0.05em;
|
|
390
|
+
color: var(--text-muted);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.bridge-title {
|
|
394
|
+
font-size: 1rem;
|
|
395
|
+
font-weight: 700;
|
|
396
|
+
margin-top: 0.25rem;
|
|
397
|
+
}
|
|
888
398
|
|
|
889
|
-
.
|
|
399
|
+
.bridge-connector {
|
|
400
|
+
display: flex;
|
|
401
|
+
align-items: center;
|
|
890
402
|
justify-content: center;
|
|
403
|
+
color: var(--text-dim);
|
|
891
404
|
}
|
|
892
405
|
|
|
893
|
-
.
|
|
406
|
+
.bridge-connector svg {
|
|
407
|
+
animation: flowRight 1.5s infinite;
|
|
408
|
+
}
|
|
894
409
|
|
|
895
|
-
|
|
410
|
+
@keyframes flowRight {
|
|
411
|
+
0%,
|
|
412
|
+
100% {
|
|
413
|
+
opacity: 0.3;
|
|
414
|
+
transform: translateX(-5px);
|
|
415
|
+
}
|
|
416
|
+
50% {
|
|
417
|
+
opacity: 1;
|
|
418
|
+
transform: translateX(5px);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
896
421
|
|
|
897
|
-
.
|
|
422
|
+
.bridge-items {
|
|
423
|
+
display: grid;
|
|
424
|
+
grid-template-columns: repeat(3, 1fr);
|
|
425
|
+
gap: 0.75rem;
|
|
426
|
+
margin-top: 1.5rem;
|
|
427
|
+
padding-top: 1.5rem;
|
|
428
|
+
border-top: 1px solid var(--border);
|
|
429
|
+
}
|
|
898
430
|
|
|
899
|
-
.
|
|
900
|
-
|
|
431
|
+
.bridge-item {
|
|
432
|
+
background: var(--bg-dark);
|
|
433
|
+
border: 1px solid var(--border);
|
|
434
|
+
border-radius: 0.5rem;
|
|
435
|
+
padding: 0.75rem;
|
|
436
|
+
text-align: center;
|
|
437
|
+
}
|
|
901
438
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
439
|
+
.bridge-item-icon {
|
|
440
|
+
font-size: 1.25rem;
|
|
441
|
+
margin-bottom: 0.25rem;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.bridge-item-text {
|
|
445
|
+
font-size: 0.75rem;
|
|
446
|
+
color: var(--text-muted);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/* Problem Section */
|
|
450
|
+
.problem {
|
|
451
|
+
padding: 6rem 2rem;
|
|
452
|
+
background: var(--bg-card);
|
|
453
|
+
border-top: 1px solid var(--border);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.problem-content {
|
|
457
|
+
max-width: 900px;
|
|
458
|
+
margin: 0 auto;
|
|
459
|
+
text-align: center;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.section-label {
|
|
463
|
+
display: inline-block;
|
|
464
|
+
font-size: 0.75rem;
|
|
465
|
+
font-weight: 700;
|
|
466
|
+
text-transform: uppercase;
|
|
467
|
+
letter-spacing: 0.1em;
|
|
468
|
+
color: var(--ruby);
|
|
469
|
+
margin-bottom: 1rem;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.section-title {
|
|
473
|
+
font-size: clamp(2rem, 4vw, 2.75rem);
|
|
474
|
+
font-weight: 800;
|
|
475
|
+
margin-bottom: 1.5rem;
|
|
476
|
+
letter-spacing: -0.025em;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
.section-description {
|
|
480
|
+
font-size: 1.125rem;
|
|
481
|
+
color: var(--text-muted);
|
|
482
|
+
max-width: 700px;
|
|
483
|
+
margin: 0 auto 3rem;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
.pain-points {
|
|
487
|
+
display: grid;
|
|
488
|
+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
489
|
+
gap: 1.5rem;
|
|
490
|
+
text-align: left;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
.pain-point {
|
|
494
|
+
background: var(--bg-dark);
|
|
495
|
+
border: 1px solid var(--border);
|
|
496
|
+
border-radius: 1rem;
|
|
497
|
+
padding: 1.5rem;
|
|
498
|
+
position: relative;
|
|
499
|
+
overflow: hidden;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
.pain-point::before {
|
|
503
|
+
content: "";
|
|
504
|
+
position: absolute;
|
|
505
|
+
top: 0;
|
|
506
|
+
left: 0;
|
|
507
|
+
right: 0;
|
|
508
|
+
height: 3px;
|
|
509
|
+
background: linear-gradient(90deg, var(--ruby), var(--primary-light));
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
.pain-point-icon {
|
|
513
|
+
font-size: 1.5rem;
|
|
514
|
+
margin-bottom: 1rem;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
.pain-point h3 {
|
|
518
|
+
font-size: 1.125rem;
|
|
519
|
+
font-weight: 700;
|
|
520
|
+
margin-bottom: 0.5rem;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.pain-point p {
|
|
524
|
+
font-size: 0.9375rem;
|
|
525
|
+
color: var(--text-muted);
|
|
526
|
+
line-height: 1.6;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/* Solution Section */
|
|
530
|
+
.solution {
|
|
531
|
+
padding: 6rem 2rem;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
.solution-header {
|
|
535
|
+
text-align: center;
|
|
536
|
+
margin-bottom: 4rem;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.solution-grid {
|
|
540
|
+
display: grid;
|
|
541
|
+
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
|
542
|
+
gap: 2rem;
|
|
543
|
+
max-width: 1200px;
|
|
544
|
+
margin: 0 auto;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
.solution-card {
|
|
548
|
+
background: var(--bg-card);
|
|
549
|
+
border: 1px solid var(--border);
|
|
550
|
+
border-radius: 1.25rem;
|
|
551
|
+
padding: 2rem;
|
|
552
|
+
transition: all 0.3s;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
.solution-card:hover {
|
|
556
|
+
border-color: var(--ruby);
|
|
557
|
+
transform: translateY(-4px);
|
|
558
|
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.solution-card-icon {
|
|
562
|
+
width: 56px;
|
|
563
|
+
height: 56px;
|
|
564
|
+
background: linear-gradient(
|
|
565
|
+
135deg,
|
|
566
|
+
rgba(204, 52, 45, 0.2),
|
|
567
|
+
rgba(59, 130, 246, 0.2)
|
|
568
|
+
);
|
|
569
|
+
border-radius: 1rem;
|
|
570
|
+
display: flex;
|
|
571
|
+
align-items: center;
|
|
572
|
+
justify-content: center;
|
|
573
|
+
font-size: 1.75rem;
|
|
574
|
+
margin-bottom: 1.5rem;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
.solution-card h3 {
|
|
578
|
+
font-size: 1.25rem;
|
|
579
|
+
font-weight: 700;
|
|
580
|
+
margin-bottom: 0.75rem;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
.solution-card p {
|
|
584
|
+
font-size: 0.9375rem;
|
|
585
|
+
color: var(--text-muted);
|
|
586
|
+
line-height: 1.7;
|
|
587
|
+
margin-bottom: 1rem;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
.solution-card-features {
|
|
591
|
+
display: flex;
|
|
592
|
+
flex-wrap: wrap;
|
|
593
|
+
gap: 0.5rem;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
.solution-card-feature {
|
|
597
|
+
font-size: 0.75rem;
|
|
598
|
+
padding: 0.25rem 0.625rem;
|
|
599
|
+
background: var(--bg-dark);
|
|
600
|
+
border: 1px solid var(--border);
|
|
601
|
+
border-radius: 1rem;
|
|
602
|
+
color: var(--text-muted);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/* Demo Section */
|
|
606
|
+
.demo {
|
|
607
|
+
padding: 6rem 2rem;
|
|
608
|
+
background: var(--bg-card);
|
|
609
|
+
border-top: 1px solid var(--border);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
.demo-header {
|
|
613
|
+
text-align: center;
|
|
614
|
+
margin-bottom: 3rem;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
.demo-container {
|
|
618
|
+
max-width: 1000px;
|
|
619
|
+
margin: 0 auto;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
.demo-window {
|
|
623
|
+
background: linear-gradient(135deg, var(--ruby), var(--accent));
|
|
624
|
+
padding: 3px;
|
|
625
|
+
border-radius: 1rem;
|
|
626
|
+
box-shadow:
|
|
627
|
+
0 25px 80px rgba(204, 52, 45, 0.2),
|
|
628
|
+
0 10px 30px rgba(0, 0, 0, 0.3);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
.demo-window-inner {
|
|
632
|
+
background: var(--bg-dark);
|
|
633
|
+
border-radius: calc(1rem - 3px);
|
|
634
|
+
overflow: hidden;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
.demo-header-bar {
|
|
638
|
+
display: flex;
|
|
639
|
+
align-items: center;
|
|
640
|
+
gap: 0.5rem;
|
|
641
|
+
padding: 1rem 1.25rem;
|
|
642
|
+
background: var(--bg-card);
|
|
643
|
+
border-bottom: 1px solid var(--border);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
.demo-dot {
|
|
647
|
+
width: 12px;
|
|
648
|
+
height: 12px;
|
|
649
|
+
border-radius: 50%;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
.demo-dot.red {
|
|
653
|
+
background: #ff5f57;
|
|
654
|
+
}
|
|
655
|
+
.demo-dot.yellow {
|
|
656
|
+
background: #febc2e;
|
|
657
|
+
}
|
|
658
|
+
.demo-dot.green {
|
|
659
|
+
background: #28c840;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
.demo-url {
|
|
663
|
+
flex: 1;
|
|
664
|
+
text-align: center;
|
|
665
|
+
font-size: 0.8125rem;
|
|
666
|
+
color: var(--text-dim);
|
|
667
|
+
font-family: "JetBrains Mono", monospace;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
.demo-content {
|
|
671
|
+
padding: 2rem;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
.demo-nav {
|
|
675
|
+
display: flex;
|
|
905
676
|
gap: 1rem;
|
|
677
|
+
margin-bottom: 2rem;
|
|
678
|
+
padding-bottom: 1rem;
|
|
679
|
+
border-bottom: 1px solid var(--border);
|
|
906
680
|
}
|
|
907
681
|
|
|
908
|
-
.nav-
|
|
682
|
+
.demo-nav-item {
|
|
683
|
+
padding: 0.5rem 1rem;
|
|
684
|
+
background: var(--bg-card);
|
|
685
|
+
border: 1px solid var(--border);
|
|
686
|
+
border-radius: 0.5rem;
|
|
687
|
+
font-size: 0.875rem;
|
|
688
|
+
color: var(--text-muted);
|
|
689
|
+
}
|
|
909
690
|
|
|
910
|
-
.
|
|
691
|
+
.demo-nav-item.active {
|
|
692
|
+
background: var(--ruby);
|
|
693
|
+
border-color: var(--ruby);
|
|
694
|
+
color: white;
|
|
695
|
+
}
|
|
911
696
|
|
|
912
|
-
.
|
|
697
|
+
.demo-stats {
|
|
698
|
+
display: grid;
|
|
699
|
+
grid-template-columns: repeat(3, 1fr);
|
|
700
|
+
gap: 1rem;
|
|
701
|
+
margin-bottom: 2rem;
|
|
702
|
+
}
|
|
913
703
|
|
|
914
|
-
.
|
|
704
|
+
.demo-stat {
|
|
705
|
+
background: var(--bg-card);
|
|
706
|
+
border: 1px solid var(--border);
|
|
707
|
+
border-radius: 0.75rem;
|
|
708
|
+
padding: 1.5rem;
|
|
709
|
+
text-align: center;
|
|
710
|
+
}
|
|
915
711
|
|
|
916
|
-
.
|
|
712
|
+
.demo-stat-value {
|
|
713
|
+
font-size: 2.5rem;
|
|
714
|
+
font-weight: 800;
|
|
715
|
+
background: linear-gradient(135deg, var(--ruby), var(--accent));
|
|
716
|
+
-webkit-background-clip: text;
|
|
717
|
+
-webkit-text-fill-color: transparent;
|
|
718
|
+
}
|
|
917
719
|
|
|
918
|
-
.
|
|
720
|
+
.demo-stat-label {
|
|
721
|
+
font-size: 0.75rem;
|
|
722
|
+
color: var(--text-dim);
|
|
723
|
+
text-transform: uppercase;
|
|
724
|
+
letter-spacing: 0.05em;
|
|
725
|
+
}
|
|
919
726
|
|
|
920
|
-
.
|
|
727
|
+
.demo-cards {
|
|
728
|
+
display: grid;
|
|
729
|
+
grid-template-columns: repeat(2, 1fr);
|
|
730
|
+
gap: 1rem;
|
|
731
|
+
}
|
|
921
732
|
|
|
922
|
-
.
|
|
733
|
+
.demo-card {
|
|
734
|
+
background: var(--bg-card);
|
|
735
|
+
border: 1px solid var(--border);
|
|
736
|
+
border-radius: 0.75rem;
|
|
737
|
+
padding: 1.25rem;
|
|
738
|
+
transition: all 0.2s;
|
|
739
|
+
}
|
|
923
740
|
|
|
924
|
-
.
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
741
|
+
.demo-card:hover {
|
|
742
|
+
border-color: var(--border-light);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
.demo-card-header {
|
|
746
|
+
display: flex;
|
|
747
|
+
justify-content: space-between;
|
|
748
|
+
align-items: center;
|
|
749
|
+
margin-bottom: 0.75rem;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
.demo-card-title {
|
|
753
|
+
font-weight: 600;
|
|
754
|
+
font-size: 0.9375rem;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
.demo-card-badge {
|
|
758
|
+
font-size: 0.6875rem;
|
|
759
|
+
padding: 0.25rem 0.5rem;
|
|
760
|
+
background: rgba(34, 197, 94, 0.15);
|
|
761
|
+
color: var(--success);
|
|
762
|
+
border-radius: 0.25rem;
|
|
763
|
+
font-weight: 600;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
.demo-card-meta {
|
|
767
|
+
font-size: 0.8125rem;
|
|
768
|
+
color: var(--text-dim);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/* How it Works */
|
|
772
|
+
.how-it-works {
|
|
773
|
+
padding: 6rem 2rem;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
.how-header {
|
|
777
|
+
text-align: center;
|
|
778
|
+
margin-bottom: 4rem;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
.steps {
|
|
782
|
+
max-width: 800px;
|
|
783
|
+
margin: 0 auto;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
.step {
|
|
787
|
+
display: flex;
|
|
788
|
+
gap: 2rem;
|
|
789
|
+
margin-bottom: 3rem;
|
|
790
|
+
position: relative;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
.step:not(:last-child)::after {
|
|
794
|
+
content: "";
|
|
795
|
+
position: absolute;
|
|
796
|
+
left: 28px;
|
|
797
|
+
top: 60px;
|
|
798
|
+
bottom: -30px;
|
|
799
|
+
width: 2px;
|
|
800
|
+
background: linear-gradient(to bottom, var(--ruby), transparent);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
.step-number {
|
|
804
|
+
width: 56px;
|
|
805
|
+
height: 56px;
|
|
806
|
+
min-width: 56px;
|
|
807
|
+
background: linear-gradient(135deg, var(--ruby), var(--primary));
|
|
808
|
+
border-radius: 50%;
|
|
809
|
+
display: flex;
|
|
810
|
+
align-items: center;
|
|
811
|
+
justify-content: center;
|
|
812
|
+
font-weight: 800;
|
|
813
|
+
font-size: 1.25rem;
|
|
814
|
+
color: white;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
.step-content {
|
|
818
|
+
flex: 1;
|
|
819
|
+
padding-top: 0.5rem;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
.step-content h3 {
|
|
823
|
+
font-size: 1.375rem;
|
|
824
|
+
font-weight: 700;
|
|
825
|
+
margin-bottom: 0.5rem;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
.step-content p {
|
|
829
|
+
color: var(--text-muted);
|
|
830
|
+
margin-bottom: 1rem;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
.step-code {
|
|
834
|
+
background: var(--bg-card);
|
|
835
|
+
border: 1px solid var(--border);
|
|
836
|
+
border-radius: 0.75rem;
|
|
837
|
+
padding: 1.25rem;
|
|
838
|
+
font-family: "JetBrains Mono", monospace;
|
|
839
|
+
font-size: 0.875rem;
|
|
840
|
+
overflow-x: auto;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
.step-code .comment {
|
|
844
|
+
color: var(--text-dim);
|
|
845
|
+
}
|
|
846
|
+
.step-code .keyword {
|
|
847
|
+
color: #f472b6;
|
|
848
|
+
}
|
|
849
|
+
.step-code .string {
|
|
850
|
+
color: #4ade80;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
/* CTA */
|
|
854
|
+
.cta {
|
|
855
|
+
padding: 8rem 2rem;
|
|
856
|
+
text-align: center;
|
|
857
|
+
background: var(--bg-card);
|
|
858
|
+
border-top: 1px solid var(--border);
|
|
859
|
+
position: relative;
|
|
860
|
+
overflow: hidden;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
.cta::before {
|
|
864
|
+
content: "";
|
|
865
|
+
position: absolute;
|
|
866
|
+
top: 50%;
|
|
867
|
+
left: 50%;
|
|
868
|
+
transform: translate(-50%, -50%);
|
|
869
|
+
width: 800px;
|
|
870
|
+
height: 800px;
|
|
871
|
+
background: radial-gradient(
|
|
872
|
+
ellipse at center,
|
|
873
|
+
rgba(204, 52, 45, 0.1) 0%,
|
|
874
|
+
transparent 60%
|
|
875
|
+
);
|
|
876
|
+
pointer-events: none;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
.cta-content {
|
|
880
|
+
max-width: 700px;
|
|
881
|
+
margin: 0 auto;
|
|
882
|
+
position: relative;
|
|
883
|
+
z-index: 1;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
.cta h2 {
|
|
887
|
+
font-size: clamp(2rem, 4vw, 3rem);
|
|
888
|
+
font-weight: 800;
|
|
889
|
+
margin-bottom: 1rem;
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
.cta p {
|
|
893
|
+
font-size: 1.25rem;
|
|
894
|
+
color: var(--text-muted);
|
|
895
|
+
margin-bottom: 2rem;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
.cta-buttons {
|
|
899
|
+
display: flex;
|
|
900
|
+
gap: 1rem;
|
|
901
|
+
justify-content: center;
|
|
902
|
+
flex-wrap: wrap;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
.install-box {
|
|
906
|
+
display: inline-flex;
|
|
907
|
+
align-items: center;
|
|
908
|
+
gap: 1rem;
|
|
909
|
+
background: var(--bg-dark);
|
|
910
|
+
border: 1px solid var(--border);
|
|
911
|
+
border-radius: 0.75rem;
|
|
912
|
+
padding: 1rem 1.5rem;
|
|
913
|
+
font-family: "JetBrains Mono", monospace;
|
|
914
|
+
font-size: 0.9375rem;
|
|
915
|
+
margin-top: 2rem;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
.install-box code {
|
|
919
|
+
color: var(--ruby-light);
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
.copy-btn {
|
|
923
|
+
background: none;
|
|
924
|
+
border: none;
|
|
925
|
+
color: var(--text-muted);
|
|
926
|
+
cursor: pointer;
|
|
927
|
+
padding: 0.5rem;
|
|
928
|
+
border-radius: 0.375rem;
|
|
929
|
+
transition: all 0.2s;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
.copy-btn:hover {
|
|
933
|
+
background: var(--border);
|
|
934
|
+
color: var(--text);
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
/* Footer */
|
|
938
|
+
.footer {
|
|
939
|
+
padding: 3rem 2rem;
|
|
940
|
+
border-top: 1px solid var(--border);
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
.footer-content {
|
|
944
|
+
max-width: 1200px;
|
|
945
|
+
margin: 0 auto;
|
|
946
|
+
display: flex;
|
|
947
|
+
justify-content: space-between;
|
|
948
|
+
align-items: center;
|
|
949
|
+
flex-wrap: wrap;
|
|
950
|
+
gap: 1.5rem;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
.footer-links {
|
|
954
|
+
display: flex;
|
|
955
|
+
gap: 2rem;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
.footer-links a {
|
|
959
|
+
color: var(--text-muted);
|
|
960
|
+
text-decoration: none;
|
|
961
|
+
font-size: 0.875rem;
|
|
962
|
+
transition: color 0.2s;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
.footer-links a:hover {
|
|
966
|
+
color: var(--text);
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
.footer-copy {
|
|
970
|
+
color: var(--text-dim);
|
|
971
|
+
font-size: 0.875rem;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
.footer-copy a {
|
|
975
|
+
color: var(--ruby-light);
|
|
976
|
+
text-decoration: none;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
.footer-copy a:hover {
|
|
980
|
+
text-decoration: underline;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
/* Responsive */
|
|
984
|
+
@media (max-width: 968px) {
|
|
985
|
+
.hero-content {
|
|
986
|
+
grid-template-columns: 1fr;
|
|
987
|
+
text-align: center;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
.hero-text {
|
|
991
|
+
max-width: 100%;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
.hero-buttons,
|
|
995
|
+
.hero-stats {
|
|
996
|
+
justify-content: center;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
.hero-stat {
|
|
1000
|
+
text-align: center;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
.bridge-row {
|
|
1004
|
+
flex-direction: column;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
.demo-stats {
|
|
1008
|
+
grid-template-columns: 1fr;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
.demo-cards {
|
|
1012
|
+
grid-template-columns: 1fr;
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
@media (max-width: 768px) {
|
|
1017
|
+
.navbar-content {
|
|
1018
|
+
flex-direction: column;
|
|
1019
|
+
gap: 1rem;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
.nav-links {
|
|
1023
|
+
gap: 1rem;
|
|
1024
|
+
flex-wrap: wrap;
|
|
1025
|
+
justify-content: center;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
.hero {
|
|
1029
|
+
padding: 6rem 1.5rem 3rem;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
.step {
|
|
1033
|
+
flex-direction: column;
|
|
1034
|
+
text-align: center;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
.step:not(:last-child)::after {
|
|
1038
|
+
display: none;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
.step-number {
|
|
1042
|
+
margin: 0 auto;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
.pain-points {
|
|
1046
|
+
grid-template-columns: 1fr;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
.solution-grid {
|
|
1050
|
+
grid-template-columns: 1fr;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
.footer-content {
|
|
1054
|
+
flex-direction: column;
|
|
1055
|
+
text-align: center;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
.footer-links {
|
|
1059
|
+
flex-wrap: wrap;
|
|
1060
|
+
justify-content: center;
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
</style>
|
|
1064
|
+
</head>
|
|
1065
|
+
<body>
|
|
1066
|
+
<!-- Navbar -->
|
|
1067
|
+
<nav class="navbar">
|
|
1068
|
+
<div class="navbar-content">
|
|
1069
|
+
<a href="#" class="logo">
|
|
1070
|
+
<img
|
|
1071
|
+
src="https://raw.githubusercontent.com/ArshdeepGrover/rails-map/main/docs/logo.png"
|
|
1072
|
+
alt="RailsMap"
|
|
1073
|
+
class="logo-img"
|
|
1074
|
+
onerror="this.style.display = 'none'"
|
|
1075
|
+
/>
|
|
1076
|
+
<span class="logo-text">Rails<span>Map</span></span>
|
|
1077
|
+
</a>
|
|
1078
|
+
<div class="nav-links">
|
|
1079
|
+
<a href="#problem">Why RailsMap</a>
|
|
1080
|
+
<a href="#features">Features</a>
|
|
1081
|
+
<a href="#how-it-works">Get Started</a>
|
|
1082
|
+
<a href="https://github.com/ArshdeepGrover/rails-map" target="_blank"
|
|
1083
|
+
>GitHub</a
|
|
1084
|
+
>
|
|
1085
|
+
<a
|
|
1086
|
+
href="https://rubygems.org/gems/rails_map"
|
|
1087
|
+
target="_blank"
|
|
1088
|
+
class="nav-btn"
|
|
1089
|
+
>Install Free</a
|
|
1090
|
+
>
|
|
987
1091
|
</div>
|
|
988
1092
|
</div>
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1093
|
+
</nav>
|
|
1094
|
+
|
|
1095
|
+
<!-- Hero -->
|
|
1096
|
+
<section class="hero">
|
|
1097
|
+
<div class="hero-content">
|
|
1098
|
+
<div class="hero-text">
|
|
1099
|
+
<div class="hero-badge">
|
|
1100
|
+
<span class="hero-badge-dot"></span>
|
|
1101
|
+
Open Source · MIT License
|
|
1102
|
+
</div>
|
|
1103
|
+
<h1>
|
|
1104
|
+
The <span class="highlight">missing bridge</span> between your
|
|
1105
|
+
backend & frontend team
|
|
1106
|
+
</h1>
|
|
1107
|
+
<p class="hero-description">
|
|
1108
|
+
Stop wasting hours explaining your Rails API to frontend developers.
|
|
1109
|
+
RailsMap automatically maps your routes, controllers, and models
|
|
1110
|
+
into beautiful, interactive documentation that everyone can
|
|
1111
|
+
understand.
|
|
1112
|
+
</p>
|
|
1113
|
+
<div class="hero-buttons">
|
|
1114
|
+
<a href="#how-it-works" class="btn btn-primary">
|
|
1115
|
+
Get Started Free
|
|
1116
|
+
<svg
|
|
1117
|
+
width="20"
|
|
1118
|
+
height="20"
|
|
1119
|
+
viewBox="0 0 24 24"
|
|
1120
|
+
fill="none"
|
|
1121
|
+
stroke="currentColor"
|
|
1122
|
+
stroke-width="2"
|
|
1123
|
+
>
|
|
1124
|
+
<path d="M5 12h14M12 5l7 7-7 7" />
|
|
1001
1125
|
</svg>
|
|
1002
|
-
</
|
|
1003
|
-
<
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1126
|
+
</a>
|
|
1127
|
+
<a
|
|
1128
|
+
href="https://github.com/ArshdeepGrover/rails-map"
|
|
1129
|
+
target="_blank"
|
|
1130
|
+
class="btn btn-secondary"
|
|
1131
|
+
>
|
|
1132
|
+
<svg
|
|
1133
|
+
width="20"
|
|
1134
|
+
height="20"
|
|
1135
|
+
viewBox="0 0 24 24"
|
|
1136
|
+
fill="currentColor"
|
|
1137
|
+
>
|
|
1138
|
+
<path
|
|
1139
|
+
d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"
|
|
1140
|
+
/>
|
|
1011
1141
|
</svg>
|
|
1142
|
+
Star on GitHub
|
|
1143
|
+
</a>
|
|
1144
|
+
</div>
|
|
1145
|
+
<div class="hero-stats">
|
|
1146
|
+
<div class="hero-stat">
|
|
1147
|
+
<div class="hero-stat-value">Zero</div>
|
|
1148
|
+
<div class="hero-stat-label">Configuration</div>
|
|
1012
1149
|
</div>
|
|
1013
|
-
<div class="
|
|
1014
|
-
<div class="
|
|
1015
|
-
<div class="
|
|
1016
|
-
<div class="bridge-title">React / Angular</div>
|
|
1150
|
+
<div class="hero-stat">
|
|
1151
|
+
<div class="hero-stat-value">30 sec</div>
|
|
1152
|
+
<div class="hero-stat-label">Setup Time</div>
|
|
1017
1153
|
</div>
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
<div class="bridge-item-icon">🛣️</div>
|
|
1022
|
-
<div class="bridge-item-text">Routes</div>
|
|
1154
|
+
<div class="hero-stat">
|
|
1155
|
+
<div class="hero-stat-value">100%</div>
|
|
1156
|
+
<div class="hero-stat-label">Automatic</div>
|
|
1023
1157
|
</div>
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1158
|
+
</div>
|
|
1159
|
+
</div>
|
|
1160
|
+
|
|
1161
|
+
<div class="hero-visual">
|
|
1162
|
+
<div class="bridge-diagram">
|
|
1163
|
+
<div class="bridge-row">
|
|
1164
|
+
<div class="bridge-box backend">
|
|
1165
|
+
<div class="bridge-icon">💎</div>
|
|
1166
|
+
<div class="bridge-label">Backend</div>
|
|
1167
|
+
<div class="bridge-title">Rails API</div>
|
|
1168
|
+
</div>
|
|
1169
|
+
<div class="bridge-connector">
|
|
1170
|
+
<svg width="40" height="24" viewBox="0 0 40 24" fill="none">
|
|
1171
|
+
<path
|
|
1172
|
+
d="M0 12H40M32 4L40 12L32 20"
|
|
1173
|
+
stroke="currentColor"
|
|
1174
|
+
stroke-width="2"
|
|
1175
|
+
/>
|
|
1176
|
+
</svg>
|
|
1177
|
+
</div>
|
|
1178
|
+
<div class="bridge-box center">
|
|
1179
|
+
<div class="bridge-icon">🗺️</div>
|
|
1180
|
+
<div class="bridge-label">Bridge</div>
|
|
1181
|
+
<div class="bridge-title">RailsMap</div>
|
|
1182
|
+
</div>
|
|
1183
|
+
<div class="bridge-connector">
|
|
1184
|
+
<svg width="40" height="24" viewBox="0 0 40 24" fill="none">
|
|
1185
|
+
<path
|
|
1186
|
+
d="M0 12H40M32 4L40 12L32 20"
|
|
1187
|
+
stroke="currentColor"
|
|
1188
|
+
stroke-width="2"
|
|
1189
|
+
/>
|
|
1190
|
+
</svg>
|
|
1191
|
+
</div>
|
|
1192
|
+
<div class="bridge-box frontend">
|
|
1193
|
+
<div class="bridge-icon">⚛️</div>
|
|
1194
|
+
<div class="bridge-label">Frontend</div>
|
|
1195
|
+
<div class="bridge-title">React / Angular</div>
|
|
1196
|
+
</div>
|
|
1027
1197
|
</div>
|
|
1028
|
-
<div class="bridge-
|
|
1029
|
-
<div class="bridge-item
|
|
1030
|
-
|
|
1198
|
+
<div class="bridge-items">
|
|
1199
|
+
<div class="bridge-item">
|
|
1200
|
+
<div class="bridge-item-icon">🛣️</div>
|
|
1201
|
+
<div class="bridge-item-text">Routes</div>
|
|
1202
|
+
</div>
|
|
1203
|
+
<div class="bridge-item">
|
|
1204
|
+
<div class="bridge-item-icon">🎮</div>
|
|
1205
|
+
<div class="bridge-item-text">Controllers</div>
|
|
1206
|
+
</div>
|
|
1207
|
+
<div class="bridge-item">
|
|
1208
|
+
<div class="bridge-item-icon">📊</div>
|
|
1209
|
+
<div class="bridge-item-text">Models</div>
|
|
1210
|
+
</div>
|
|
1031
1211
|
</div>
|
|
1032
1212
|
</div>
|
|
1033
1213
|
</div>
|
|
1034
1214
|
</div>
|
|
1035
|
-
</
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
<
|
|
1065
|
-
|
|
1215
|
+
</section>
|
|
1216
|
+
|
|
1217
|
+
<!-- Problem Section -->
|
|
1218
|
+
<section class="problem" id="problem">
|
|
1219
|
+
<div class="problem-content">
|
|
1220
|
+
<span class="section-label">The Problem</span>
|
|
1221
|
+
<h2 class="section-title">Sound familiar?</h2>
|
|
1222
|
+
<p class="section-description">
|
|
1223
|
+
Every Rails developer knows the pain. Your backend is powerful, but
|
|
1224
|
+
getting the frontend team on the same page feels impossible.
|
|
1225
|
+
</p>
|
|
1226
|
+
<div class="pain-points">
|
|
1227
|
+
<div class="pain-point">
|
|
1228
|
+
<div class="pain-point-icon">😩</div>
|
|
1229
|
+
<h3>"What endpoints do we have?"</h3>
|
|
1230
|
+
<p>
|
|
1231
|
+
Frontend devs constantly asking about available routes, required
|
|
1232
|
+
params, and response formats. You spend more time explaining than
|
|
1233
|
+
coding.
|
|
1234
|
+
</p>
|
|
1235
|
+
</div>
|
|
1236
|
+
<div class="pain-point">
|
|
1237
|
+
<div class="pain-point-icon">📝</div>
|
|
1238
|
+
<h3>Documentation is always outdated</h3>
|
|
1239
|
+
<p>
|
|
1240
|
+
You wrote docs once, then the API changed. Now nobody trusts them,
|
|
1241
|
+
and you're back to Slack messages and screen shares.
|
|
1242
|
+
</p>
|
|
1243
|
+
</div>
|
|
1244
|
+
<div class="pain-point">
|
|
1245
|
+
<div class="pain-point-icon">🔄</div>
|
|
1246
|
+
<h3>Constant context switching</h3>
|
|
1247
|
+
<p>
|
|
1248
|
+
Every time someone needs API info, you have to stop what you're
|
|
1249
|
+
doing, dig through controllers, and piece together the answer.
|
|
1250
|
+
</p>
|
|
1251
|
+
</div>
|
|
1252
|
+
<div class="pain-point">
|
|
1253
|
+
<div class="pain-point-icon">🤷</div>
|
|
1254
|
+
<h3>"What columns does this model have?"</h3>
|
|
1255
|
+
<p>
|
|
1256
|
+
New team members struggle to understand your data structure. They
|
|
1257
|
+
open migration files, check schemas, ask questions...
|
|
1258
|
+
</p>
|
|
1259
|
+
</div>
|
|
1066
1260
|
</div>
|
|
1067
1261
|
</div>
|
|
1068
|
-
</
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
</div>
|
|
1080
|
-
<div class="solution-grid">
|
|
1081
|
-
<div class="solution-card">
|
|
1082
|
-
<div class="solution-card-icon">🛣️</div>
|
|
1083
|
-
<h3>Automatic Route Discovery</h3>
|
|
1084
|
-
<p>Every route in your Rails app is automatically discovered and documented. HTTP methods, paths, constraints, and route names—all mapped instantly.</p>
|
|
1085
|
-
<div class="solution-card-features">
|
|
1086
|
-
<span class="solution-card-feature">GET / POST / PUT / DELETE</span>
|
|
1087
|
-
<span class="solution-card-feature">Route Params</span>
|
|
1088
|
-
<span class="solution-card-feature">Constraints</span>
|
|
1089
|
-
</div>
|
|
1262
|
+
</section>
|
|
1263
|
+
|
|
1264
|
+
<!-- Solution Section -->
|
|
1265
|
+
<section class="solution" id="features">
|
|
1266
|
+
<div class="solution-header">
|
|
1267
|
+
<span class="section-label">The Solution</span>
|
|
1268
|
+
<h2 class="section-title">RailsMap does the work for you</h2>
|
|
1269
|
+
<p class="section-description">
|
|
1270
|
+
Install once, forget forever. Your API documentation stays in sync
|
|
1271
|
+
automatically.
|
|
1272
|
+
</p>
|
|
1090
1273
|
</div>
|
|
1091
|
-
<div class="solution-
|
|
1092
|
-
<div class="solution-card
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1274
|
+
<div class="solution-grid">
|
|
1275
|
+
<div class="solution-card">
|
|
1276
|
+
<div class="solution-card-icon">🛣️</div>
|
|
1277
|
+
<h3>Automatic Route Discovery</h3>
|
|
1278
|
+
<p>
|
|
1279
|
+
Every route in your Rails app is automatically discovered and
|
|
1280
|
+
documented. HTTP methods, paths, constraints, and route names—all
|
|
1281
|
+
mapped instantly.
|
|
1282
|
+
</p>
|
|
1283
|
+
<div class="solution-card-features">
|
|
1284
|
+
<span class="solution-card-feature">GET / POST / PUT / DELETE</span>
|
|
1285
|
+
<span class="solution-card-feature">Route Params</span>
|
|
1286
|
+
<span class="solution-card-feature">Constraints</span>
|
|
1287
|
+
</div>
|
|
1099
1288
|
</div>
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
<
|
|
1289
|
+
<div class="solution-card">
|
|
1290
|
+
<div class="solution-card-icon">📊</div>
|
|
1291
|
+
<h3>Model Introspection</h3>
|
|
1292
|
+
<p>
|
|
1293
|
+
Database columns, associations, validations, and scopes are
|
|
1294
|
+
extracted automatically. Your data structure, documented without
|
|
1295
|
+
writing a single line.
|
|
1296
|
+
</p>
|
|
1297
|
+
<div class="solution-card-features">
|
|
1298
|
+
<span class="solution-card-feature">Columns & Types</span>
|
|
1299
|
+
<span class="solution-card-feature">Associations</span>
|
|
1300
|
+
<span class="solution-card-feature">Validations</span>
|
|
1301
|
+
</div>
|
|
1109
1302
|
</div>
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
<
|
|
1303
|
+
<div class="solution-card">
|
|
1304
|
+
<div class="solution-card-icon">🎨</div>
|
|
1305
|
+
<h3>Beautiful Dark UI</h3>
|
|
1306
|
+
<p>
|
|
1307
|
+
Modern, responsive interface that developers actually want to use.
|
|
1308
|
+
Searchable, filterable, and easy to navigate. Looks great on any
|
|
1309
|
+
device.
|
|
1310
|
+
</p>
|
|
1311
|
+
<div class="solution-card-features">
|
|
1312
|
+
<span class="solution-card-feature">Dark Theme</span>
|
|
1313
|
+
<span class="solution-card-feature">Instant Search</span>
|
|
1314
|
+
<span class="solution-card-feature">Responsive</span>
|
|
1315
|
+
</div>
|
|
1119
1316
|
</div>
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
<
|
|
1317
|
+
<div class="solution-card">
|
|
1318
|
+
<div class="solution-card-icon">🔒</div>
|
|
1319
|
+
<h3>Environment-Based Auth</h3>
|
|
1320
|
+
<p>
|
|
1321
|
+
Secure by default with environment variables. No database, no
|
|
1322
|
+
migrations—just set RAILS_MAP_USERNAME and RAILS_MAP_PASSWORD.
|
|
1323
|
+
Defaults to admin/password.
|
|
1324
|
+
</p>
|
|
1325
|
+
<div class="solution-card-features">
|
|
1326
|
+
<span class="solution-card-feature">No Database</span>
|
|
1327
|
+
<span class="solution-card-feature">ENV Variables</span>
|
|
1328
|
+
<span class="solution-card-feature">Default Credentials</span>
|
|
1329
|
+
</div>
|
|
1129
1330
|
</div>
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
<
|
|
1138
|
-
|
|
1331
|
+
<div class="solution-card">
|
|
1332
|
+
<div class="solution-card-icon">⚡</div>
|
|
1333
|
+
<h3>Zero Configuration</h3>
|
|
1334
|
+
<p>
|
|
1335
|
+
Run one command. That's it. No config files, no annotations, no
|
|
1336
|
+
comments. RailsMap reads your code and generates docs automatically.
|
|
1337
|
+
</p>
|
|
1338
|
+
<div class="solution-card-features">
|
|
1339
|
+
<span class="solution-card-feature">One Command</span>
|
|
1340
|
+
<span class="solution-card-feature">Auto-mount</span>
|
|
1341
|
+
<span class="solution-card-feature">Works Instantly</span>
|
|
1342
|
+
</div>
|
|
1139
1343
|
</div>
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
</div>
|
|
1153
|
-
<div class="demo-container">
|
|
1154
|
-
<div class="demo-window">
|
|
1155
|
-
<div class="demo-window-inner">
|
|
1156
|
-
<div class="demo-header-bar">
|
|
1157
|
-
<span class="demo-dot red"></span>
|
|
1158
|
-
<span class="demo-dot yellow"></span>
|
|
1159
|
-
<span class="demo-dot green"></span>
|
|
1160
|
-
<span class="demo-url">localhost:3000/api-doc</span>
|
|
1344
|
+
<div class="solution-card">
|
|
1345
|
+
<div class="solution-card-icon">🔄</div>
|
|
1346
|
+
<h3>Always In Sync</h3>
|
|
1347
|
+
<p>
|
|
1348
|
+
Add a route? It's documented. Change a model? Updated automatically.
|
|
1349
|
+
Your docs are always current because they come from your actual
|
|
1350
|
+
code.
|
|
1351
|
+
</p>
|
|
1352
|
+
<div class="solution-card-features">
|
|
1353
|
+
<span class="solution-card-feature">Live Updates</span>
|
|
1354
|
+
<span class="solution-card-feature">No Manual Work</span>
|
|
1355
|
+
<span class="solution-card-feature">Always Accurate</span>
|
|
1161
1356
|
</div>
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1357
|
+
</div>
|
|
1358
|
+
</div>
|
|
1359
|
+
</section>
|
|
1360
|
+
|
|
1361
|
+
<!-- Demo Section -->
|
|
1362
|
+
<section class="demo">
|
|
1363
|
+
<div class="demo-header">
|
|
1364
|
+
<span class="section-label">Live Preview</span>
|
|
1365
|
+
<h2 class="section-title">See what your team will see</h2>
|
|
1366
|
+
<p class="section-description">
|
|
1367
|
+
A clean, organized view of your entire Rails API. No more digging
|
|
1368
|
+
through code.
|
|
1369
|
+
</p>
|
|
1370
|
+
</div>
|
|
1371
|
+
<div class="demo-container">
|
|
1372
|
+
<div class="demo-window">
|
|
1373
|
+
<div class="demo-window-inner">
|
|
1374
|
+
<div class="demo-header-bar">
|
|
1375
|
+
<span class="demo-dot red"></span>
|
|
1376
|
+
<span class="demo-dot yellow"></span>
|
|
1377
|
+
<span class="demo-dot green"></span>
|
|
1378
|
+
<span class="demo-url">localhost:3000/rails-map</span>
|
|
1167
1379
|
</div>
|
|
1168
|
-
<div class="demo-
|
|
1169
|
-
<div class="demo-
|
|
1170
|
-
<
|
|
1171
|
-
<
|
|
1380
|
+
<div class="demo-content">
|
|
1381
|
+
<div class="demo-nav">
|
|
1382
|
+
<span class="demo-nav-item active">Dashboard</span>
|
|
1383
|
+
<span class="demo-nav-item">Routes</span>
|
|
1384
|
+
<span class="demo-nav-item">Models</span>
|
|
1172
1385
|
</div>
|
|
1173
|
-
<div class="demo-
|
|
1174
|
-
<div class="demo-stat
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
<div class="demo-stat">
|
|
1178
|
-
<div class="demo-stat-value">12</div>
|
|
1179
|
-
<div class="demo-stat-label">Models</div>
|
|
1180
|
-
</div>
|
|
1181
|
-
</div>
|
|
1182
|
-
<div class="demo-cards">
|
|
1183
|
-
<div class="demo-card">
|
|
1184
|
-
<div class="demo-card-header">
|
|
1185
|
-
<span class="demo-card-title">Api::V1::UsersController</span>
|
|
1186
|
-
<span class="demo-card-badge">7 routes</span>
|
|
1386
|
+
<div class="demo-stats">
|
|
1387
|
+
<div class="demo-stat">
|
|
1388
|
+
<div class="demo-stat-value">15</div>
|
|
1389
|
+
<div class="demo-stat-label">Controllers</div>
|
|
1187
1390
|
</div>
|
|
1188
|
-
<div class="demo-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
<div class="demo-card-header">
|
|
1192
|
-
<span class="demo-card-title">Api::V1::PostsController</span>
|
|
1193
|
-
<span class="demo-card-badge">5 routes</span>
|
|
1391
|
+
<div class="demo-stat">
|
|
1392
|
+
<div class="demo-stat-value">67</div>
|
|
1393
|
+
<div class="demo-stat-label">Routes</div>
|
|
1194
1394
|
</div>
|
|
1195
|
-
<div class="demo-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
<div class="demo-card-header">
|
|
1199
|
-
<span class="demo-card-title">User</span>
|
|
1200
|
-
<span class="demo-card-badge">8 columns</span>
|
|
1395
|
+
<div class="demo-stat">
|
|
1396
|
+
<div class="demo-stat-value">12</div>
|
|
1397
|
+
<div class="demo-stat-label">Models</div>
|
|
1201
1398
|
</div>
|
|
1202
|
-
<div class="demo-card-meta">has_many :posts, has_many :comments</div>
|
|
1203
1399
|
</div>
|
|
1204
|
-
<div class="demo-
|
|
1205
|
-
<div class="demo-card
|
|
1206
|
-
<
|
|
1207
|
-
|
|
1400
|
+
<div class="demo-cards">
|
|
1401
|
+
<div class="demo-card">
|
|
1402
|
+
<div class="demo-card-header">
|
|
1403
|
+
<span class="demo-card-title"
|
|
1404
|
+
>Api::V1::UsersController</span
|
|
1405
|
+
>
|
|
1406
|
+
<span class="demo-card-badge">7 routes</span>
|
|
1407
|
+
</div>
|
|
1408
|
+
<div class="demo-card-meta">
|
|
1409
|
+
/api/v1/users · index, show, create, update, destroy
|
|
1410
|
+
</div>
|
|
1411
|
+
</div>
|
|
1412
|
+
<div class="demo-card">
|
|
1413
|
+
<div class="demo-card-header">
|
|
1414
|
+
<span class="demo-card-title"
|
|
1415
|
+
>Api::V1::PostsController</span
|
|
1416
|
+
>
|
|
1417
|
+
<span class="demo-card-badge">5 routes</span>
|
|
1418
|
+
</div>
|
|
1419
|
+
<div class="demo-card-meta">
|
|
1420
|
+
/api/v1/posts · index, show, create, update, destroy
|
|
1421
|
+
</div>
|
|
1422
|
+
</div>
|
|
1423
|
+
<div class="demo-card">
|
|
1424
|
+
<div class="demo-card-header">
|
|
1425
|
+
<span class="demo-card-title">User</span>
|
|
1426
|
+
<span class="demo-card-badge">8 columns</span>
|
|
1427
|
+
</div>
|
|
1428
|
+
<div class="demo-card-meta">
|
|
1429
|
+
has_many :posts, has_many :comments
|
|
1430
|
+
</div>
|
|
1431
|
+
</div>
|
|
1432
|
+
<div class="demo-card">
|
|
1433
|
+
<div class="demo-card-header">
|
|
1434
|
+
<span class="demo-card-title">Post</span>
|
|
1435
|
+
<span class="demo-card-badge">6 columns</span>
|
|
1436
|
+
</div>
|
|
1437
|
+
<div class="demo-card-meta">
|
|
1438
|
+
belongs_to :user, has_many :comments
|
|
1439
|
+
</div>
|
|
1208
1440
|
</div>
|
|
1209
|
-
<div class="demo-card-meta">belongs_to :user, has_many :comments</div>
|
|
1210
1441
|
</div>
|
|
1211
1442
|
</div>
|
|
1212
1443
|
</div>
|
|
1213
1444
|
</div>
|
|
1214
1445
|
</div>
|
|
1215
|
-
</
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
</
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1446
|
+
</section>
|
|
1447
|
+
|
|
1448
|
+
<!-- How it Works -->
|
|
1449
|
+
<section class="how-it-works" id="how-it-works">
|
|
1450
|
+
<div class="how-header">
|
|
1451
|
+
<span class="section-label">Get Started</span>
|
|
1452
|
+
<h2 class="section-title">Up and running in 30 seconds</h2>
|
|
1453
|
+
<p class="section-description">
|
|
1454
|
+
Seriously. Three commands and you're done.
|
|
1455
|
+
</p>
|
|
1456
|
+
</div>
|
|
1457
|
+
<div class="steps">
|
|
1458
|
+
<div class="step">
|
|
1459
|
+
<div class="step-number">1</div>
|
|
1460
|
+
<div class="step-content">
|
|
1461
|
+
<h3>Add RailsMap to your Gemfile</h3>
|
|
1462
|
+
<p>Just one line. That's all you need to add.</p>
|
|
1463
|
+
<div class="step-code">
|
|
1464
|
+
<span class="comment"># Gemfile</span><br />
|
|
1465
|
+
<span class="keyword">gem</span>
|
|
1466
|
+
<span class="string">'rails_map'</span>
|
|
1467
|
+
</div>
|
|
1236
1468
|
</div>
|
|
1237
1469
|
</div>
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1470
|
+
<div class="step">
|
|
1471
|
+
<div class="step-number">2</div>
|
|
1472
|
+
<div class="step-content">
|
|
1473
|
+
<h3>Run the install generator</h3>
|
|
1474
|
+
<p>
|
|
1475
|
+
This mounts the engine and creates the config. Set environment
|
|
1476
|
+
variables to customize credentials (defaults: admin/password).
|
|
1477
|
+
</p>
|
|
1478
|
+
<div class="step-code">
|
|
1479
|
+
$ bundle install<br />
|
|
1480
|
+
$ rails generate rails_map:install<br />
|
|
1481
|
+
<span class="comment"
|
|
1482
|
+
># Optional: export RAILS_MAP_USERNAME=your_user</span
|
|
1483
|
+
><br />
|
|
1484
|
+
<span class="comment"
|
|
1485
|
+
># Optional: export RAILS_MAP_PASSWORD=your_pass</span
|
|
1486
|
+
>
|
|
1487
|
+
</div>
|
|
1249
1488
|
</div>
|
|
1250
1489
|
</div>
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
<
|
|
1260
|
-
|
|
1490
|
+
<div class="step">
|
|
1491
|
+
<div class="step-number">3</div>
|
|
1492
|
+
<div class="step-content">
|
|
1493
|
+
<h3>Visit your docs</h3>
|
|
1494
|
+
<p>
|
|
1495
|
+
Start your server and open the documentation URL. Login with
|
|
1496
|
+
default credentials: <strong>admin/password</strong>
|
|
1497
|
+
</p>
|
|
1498
|
+
<div class="step-code">
|
|
1499
|
+
$ rails server<br />
|
|
1500
|
+
<span class="comment"># Open http://localhost:3000/rails-map</span
|
|
1501
|
+
><br />
|
|
1502
|
+
<span class="comment"
|
|
1503
|
+
># Default: username=admin, password=password</span
|
|
1504
|
+
>
|
|
1505
|
+
</div>
|
|
1261
1506
|
</div>
|
|
1262
1507
|
</div>
|
|
1263
1508
|
</div>
|
|
1264
|
-
</
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
</
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1509
|
+
</section>
|
|
1510
|
+
|
|
1511
|
+
<!-- CTA -->
|
|
1512
|
+
<section class="cta">
|
|
1513
|
+
<div class="cta-content">
|
|
1514
|
+
<h2>Stop explaining. Start shipping.</h2>
|
|
1515
|
+
<p>
|
|
1516
|
+
Give your team the documentation they need. Install RailsMap today and
|
|
1517
|
+
bridge the gap between backend and frontend—permanently.
|
|
1518
|
+
</p>
|
|
1519
|
+
<div class="cta-buttons">
|
|
1520
|
+
<a
|
|
1521
|
+
href="https://rubygems.org/gems/rails_map"
|
|
1522
|
+
target="_blank"
|
|
1523
|
+
class="btn btn-primary"
|
|
1524
|
+
>
|
|
1525
|
+
Install RailsMap Free
|
|
1526
|
+
<svg
|
|
1527
|
+
width="20"
|
|
1528
|
+
height="20"
|
|
1529
|
+
viewBox="0 0 24 24"
|
|
1530
|
+
fill="none"
|
|
1531
|
+
stroke="currentColor"
|
|
1532
|
+
stroke-width="2"
|
|
1533
|
+
>
|
|
1534
|
+
<path d="M5 12h14M12 5l7 7-7 7" />
|
|
1535
|
+
</svg>
|
|
1536
|
+
</a>
|
|
1537
|
+
<a
|
|
1538
|
+
href="https://github.com/ArshdeepGrover/rails-map"
|
|
1539
|
+
target="_blank"
|
|
1540
|
+
class="btn btn-secondary"
|
|
1541
|
+
>
|
|
1542
|
+
View on GitHub
|
|
1543
|
+
</a>
|
|
1544
|
+
</div>
|
|
1545
|
+
<div class="install-box">
|
|
1546
|
+
<code>gem install rails_map</code>
|
|
1547
|
+
<button
|
|
1548
|
+
class="copy-btn"
|
|
1549
|
+
onclick="copyToClipboard('gem install rails_map')"
|
|
1550
|
+
>
|
|
1551
|
+
<svg
|
|
1552
|
+
width="20"
|
|
1553
|
+
height="20"
|
|
1554
|
+
viewBox="0 0 24 24"
|
|
1555
|
+
fill="none"
|
|
1556
|
+
stroke="currentColor"
|
|
1557
|
+
stroke-width="2"
|
|
1558
|
+
>
|
|
1559
|
+
<rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
|
|
1560
|
+
<path
|
|
1561
|
+
d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
|
|
1562
|
+
/>
|
|
1563
|
+
</svg>
|
|
1564
|
+
</button>
|
|
1565
|
+
</div>
|
|
1305
1566
|
</div>
|
|
1306
|
-
|
|
1307
|
-
|
|
1567
|
+
</section>
|
|
1568
|
+
|
|
1569
|
+
<!-- Footer -->
|
|
1570
|
+
<footer class="footer">
|
|
1571
|
+
<div class="footer-content">
|
|
1572
|
+
<div class="footer-links">
|
|
1573
|
+
<a href="https://github.com/ArshdeepGrover/rails-map" target="_blank"
|
|
1574
|
+
>GitHub</a
|
|
1575
|
+
>
|
|
1576
|
+
<a href="https://rubygems.org/gems/rails_map" target="_blank"
|
|
1577
|
+
>RubyGems</a
|
|
1578
|
+
>
|
|
1579
|
+
<a
|
|
1580
|
+
href="https://github.com/ArshdeepGrover/rails-map/issues"
|
|
1581
|
+
target="_blank"
|
|
1582
|
+
>Issues</a
|
|
1583
|
+
>
|
|
1584
|
+
<a
|
|
1585
|
+
href="https://github.com/ArshdeepGrover/rails-map/blob/main/CHANGELOG.md"
|
|
1586
|
+
target="_blank"
|
|
1587
|
+
>Changelog</a
|
|
1588
|
+
>
|
|
1589
|
+
</div>
|
|
1590
|
+
<div class="footer-copy">
|
|
1591
|
+
Built with ❤️ by
|
|
1592
|
+
<a
|
|
1593
|
+
href="https://www.arshdeepsingh.info?utm_source=rails_map&utm_medium=footer&utm_campaign=developer_credit&utm_content=landing_page"
|
|
1594
|
+
target="_blank"
|
|
1595
|
+
>Arshdeep Singh</a
|
|
1596
|
+
>
|
|
1597
|
+
</div>
|
|
1308
1598
|
</div>
|
|
1309
|
-
</
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
btn.innerHTML = `
|
|
1599
|
+
</footer>
|
|
1600
|
+
|
|
1601
|
+
<script>
|
|
1602
|
+
function copyToClipboard(text) {
|
|
1603
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
1604
|
+
const btn = document.querySelector(".copy-btn");
|
|
1605
|
+
btn.innerHTML = `
|
|
1317
1606
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#22c55e" stroke-width="2">
|
|
1318
1607
|
<polyline points="20 6 9 17 4 12"/>
|
|
1319
1608
|
</svg>
|
|
1320
1609
|
`;
|
|
1321
|
-
|
|
1322
|
-
|
|
1610
|
+
setTimeout(() => {
|
|
1611
|
+
btn.innerHTML = `
|
|
1323
1612
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1324
1613
|
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"/>
|
|
1325
1614
|
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
|
|
1326
1615
|
</svg>
|
|
1327
1616
|
`;
|
|
1328
|
-
|
|
1617
|
+
}, 2000);
|
|
1618
|
+
});
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
// Smooth scroll
|
|
1622
|
+
document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
|
|
1623
|
+
anchor.addEventListener("click", function (e) {
|
|
1624
|
+
e.preventDefault();
|
|
1625
|
+
const target = document.querySelector(this.getAttribute("href"));
|
|
1626
|
+
if (target) {
|
|
1627
|
+
target.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
1628
|
+
}
|
|
1629
|
+
});
|
|
1329
1630
|
});
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
1631
|
+
|
|
1632
|
+
// Navbar scroll effect
|
|
1633
|
+
window.addEventListener("scroll", () => {
|
|
1634
|
+
const navbar = document.querySelector(".navbar");
|
|
1635
|
+
if (window.scrollY > 50) {
|
|
1636
|
+
navbar.style.background = "rgba(9, 9, 11, 0.95)";
|
|
1637
|
+
} else {
|
|
1638
|
+
navbar.style.background = "rgba(9, 9, 11, 0.9)";
|
|
1339
1639
|
}
|
|
1340
1640
|
});
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
// Navbar scroll effect
|
|
1344
|
-
window.addEventListener('scroll', () => {
|
|
1345
|
-
const navbar = document.querySelector('.navbar');
|
|
1346
|
-
if (window.scrollY > 50) {
|
|
1347
|
-
navbar.style.background = 'rgba(9, 9, 11, 0.95)';
|
|
1348
|
-
} else {
|
|
1349
|
-
navbar.style.background = 'rgba(9, 9, 11, 0.9)';
|
|
1350
|
-
}
|
|
1351
|
-
});
|
|
1352
|
-
</script>
|
|
1353
|
-
</body>
|
|
1641
|
+
</script>
|
|
1642
|
+
</body>
|
|
1354
1643
|
</html>
|