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.
data/docs/index.html CHANGED
@@ -1,1354 +1,1643 @@
1
- <!DOCTYPE html>
1
+ <!doctype html>
2
2
  <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>RailsMap - The Missing Bridge Between Your Rails Backend & Frontend Team</title>
7
- <meta name="description" content="RailsMap automatically maps your Rails routes, controllers, and models into beautiful, interactive documentation. Bridge the gap between backend and frontend teams instantly.">
8
- <meta name="keywords" content="rails, api documentation, ruby on rails, api docs, rails routes, rails models, developer tools">
9
- <meta property="og:title" content="RailsMap - The Missing Bridge Between Backend & Frontend">
10
- <meta property="og:description" content="Auto-generate interactive API documentation for Rails. Zero configuration.">
11
- <meta property="og:type" content="website">
12
- <link rel="preconnect" href="https://fonts.googleapis.com">
13
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
15
- <style>
16
- :root {
17
- --primary: #ef4444;
18
- --primary-dark: #dc2626;
19
- --primary-light: #f87171;
20
- --ruby: #cc342d;
21
- --ruby-light: #ff6b6b;
22
- --accent: #3b82f6;
23
- --accent-light: #60a5fa;
24
- --bg-dark: #09090b;
25
- --bg-card: #18181b;
26
- --bg-card-hover: #27272a;
27
- --text: #fafafa;
28
- --text-muted: #a1a1aa;
29
- --text-dim: #71717a;
30
- --border: #27272a;
31
- --border-light: #3f3f46;
32
- --success: #22c55e;
33
- --warning: #f59e0b;
34
- }
35
-
36
- * { margin: 0; padding: 0; box-sizing: border-box; }
37
- html { scroll-behavior: smooth; }
38
-
39
- body {
40
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
41
- background: var(--bg-dark);
42
- color: var(--text);
43
- line-height: 1.6;
44
- overflow-x: hidden;
45
- }
46
-
47
- .container { max-width: 1200px; margin: 0 auto; padding: 0 2rem; }
48
-
49
- /* Navbar */
50
- .navbar {
51
- position: fixed;
52
- top: 0;
53
- left: 0;
54
- right: 0;
55
- z-index: 100;
56
- padding: 1rem 2rem;
57
- background: rgba(9, 9, 11, 0.9);
58
- backdrop-filter: blur(20px);
59
- border-bottom: 1px solid var(--border);
60
- }
61
-
62
- .navbar-content {
63
- max-width: 1200px;
64
- margin: 0 auto;
65
- display: flex;
66
- justify-content: space-between;
67
- align-items: center;
68
- }
69
-
70
- .logo {
71
- display: flex;
72
- align-items: center;
73
- gap: 0.75rem;
74
- text-decoration: none;
75
- color: var(--text);
76
- }
77
-
78
- .logo-img {
79
- height: 40px;
80
- width: auto;
81
- }
82
-
83
- .logo-text {
84
- font-size: 1.5rem;
85
- font-weight: 800;
86
- letter-spacing: -0.025em;
87
- }
88
-
89
- .logo-text span {
90
- color: var(--ruby);
91
- }
92
-
93
- .nav-links {
94
- display: flex;
95
- align-items: center;
96
- gap: 2rem;
97
- }
98
-
99
- .nav-links a {
100
- color: var(--text-muted);
101
- text-decoration: none;
102
- font-size: 0.9375rem;
103
- font-weight: 500;
104
- transition: color 0.2s;
105
- }
106
-
107
- .nav-links a:hover { color: var(--text); }
108
-
109
- .nav-btn {
110
- padding: 0.625rem 1.25rem;
111
- background: var(--ruby);
112
- color: white !important;
113
- border-radius: 0.5rem;
114
- font-weight: 600;
115
- transition: all 0.2s;
116
- }
117
-
118
- .nav-btn:hover {
119
- background: var(--ruby-light);
120
- transform: translateY(-1px);
121
- }
122
-
123
- /* Hero */
124
- .hero {
125
- min-height: 100vh;
126
- display: flex;
127
- align-items: center;
128
- padding: 8rem 2rem 4rem;
129
- position: relative;
130
- overflow: hidden;
131
- }
132
-
133
- .hero::before {
134
- content: '';
135
- position: absolute;
136
- top: -50%;
137
- left: -50%;
138
- width: 200%;
139
- height: 200%;
140
- background:
141
- radial-gradient(ellipse at 30% 20%, rgba(204, 52, 45, 0.08) 0%, transparent 50%),
142
- radial-gradient(ellipse at 70% 80%, rgba(59, 130, 246, 0.08) 0%, transparent 50%);
143
- pointer-events: none;
144
- }
145
-
146
- .hero-content {
147
- max-width: 1200px;
148
- margin: 0 auto;
149
- display: grid;
150
- grid-template-columns: 1fr 1fr;
151
- gap: 4rem;
152
- align-items: center;
153
- position: relative;
154
- z-index: 1;
155
- }
156
-
157
- .hero-text { max-width: 600px; }
158
-
159
- .hero-badge {
160
- display: inline-flex;
161
- align-items: center;
162
- gap: 0.5rem;
163
- padding: 0.5rem 1rem;
164
- background: rgba(204, 52, 45, 0.1);
165
- border: 1px solid rgba(204, 52, 45, 0.3);
166
- border-radius: 2rem;
167
- font-size: 0.875rem;
168
- color: var(--ruby-light);
169
- margin-bottom: 1.5rem;
170
- }
171
-
172
- .hero-badge-dot {
173
- width: 8px;
174
- height: 8px;
175
- background: var(--ruby);
176
- border-radius: 50%;
177
- animation: pulse 2s infinite;
178
- }
179
-
180
- @keyframes pulse {
181
- 0%, 100% { opacity: 1; transform: scale(1); }
182
- 50% { opacity: 0.5; transform: scale(0.9); }
183
- }
184
-
185
- h1 {
186
- font-size: clamp(2.5rem, 5vw, 3.5rem);
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
- grid-template-columns: 1fr;
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
- .hero-text { max-width: 100%; }
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
- .hero-buttons, .hero-stats {
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
- .hero-stat { text-align: center; }
406
+ .bridge-connector svg {
407
+ animation: flowRight 1.5s infinite;
408
+ }
894
409
 
895
- .bridge-row { flex-direction: column; }
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
- .demo-stats { grid-template-columns: 1fr; }
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
- .demo-cards { grid-template-columns: 1fr; }
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
- @media (max-width: 768px) {
903
- .navbar-content {
904
- flex-direction: column;
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-links { gap: 1rem; flex-wrap: wrap; justify-content: center; }
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
- .hero { padding: 6rem 1.5rem 3rem; }
691
+ .demo-nav-item.active {
692
+ background: var(--ruby);
693
+ border-color: var(--ruby);
694
+ color: white;
695
+ }
911
696
 
912
- .step { flex-direction: column; text-align: center; }
697
+ .demo-stats {
698
+ display: grid;
699
+ grid-template-columns: repeat(3, 1fr);
700
+ gap: 1rem;
701
+ margin-bottom: 2rem;
702
+ }
913
703
 
914
- .step:not(:last-child)::after { display: none; }
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
- .step-number { margin: 0 auto; }
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
- .pain-points { grid-template-columns: 1fr; }
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
- .solution-grid { grid-template-columns: 1fr; }
727
+ .demo-cards {
728
+ display: grid;
729
+ grid-template-columns: repeat(2, 1fr);
730
+ gap: 1rem;
731
+ }
921
732
 
922
- .footer-content { flex-direction: column; text-align: center; }
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
- .footer-links { flex-wrap: wrap; justify-content: center; }
925
- }
926
- </style>
927
- </head>
928
- <body>
929
- <!-- Navbar -->
930
- <nav class="navbar">
931
- <div class="navbar-content">
932
- <a href="#" class="logo">
933
- <img src="https://raw.githubusercontent.com/ArshdeepGrover/rails-map/main/docs/logo.png" alt="RailsMap" class="logo-img" onerror="this.style.display='none'">
934
- <span class="logo-text">Rails<span>Map</span></span>
935
- </a>
936
- <div class="nav-links">
937
- <a href="#problem">Why RailsMap</a>
938
- <a href="#features">Features</a>
939
- <a href="#how-it-works">Get Started</a>
940
- <a href="https://github.com/ArshdeepGrover/rails-map" target="_blank">GitHub</a>
941
- <a href="https://rubygems.org/gems/rails_map" target="_blank" class="nav-btn">Install Free</a>
942
- </div>
943
- </div>
944
- </nav>
945
-
946
- <!-- Hero -->
947
- <section class="hero">
948
- <div class="hero-content">
949
- <div class="hero-text">
950
- <div class="hero-badge">
951
- <span class="hero-badge-dot"></span>
952
- Open Source · MIT License
953
- </div>
954
- <h1>
955
- The <span class="highlight">missing bridge</span> between your backend & frontend team
956
- </h1>
957
- <p class="hero-description">
958
- Stop wasting hours explaining your Rails API to frontend developers. RailsMap automatically maps your routes, controllers, and models into beautiful, interactive documentation that everyone can understand.
959
- </p>
960
- <div class="hero-buttons">
961
- <a href="#how-it-works" class="btn btn-primary">
962
- Get Started Free
963
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
964
- <path d="M5 12h14M12 5l7 7-7 7"/>
965
- </svg>
966
- </a>
967
- <a href="https://github.com/ArshdeepGrover/rails-map" target="_blank" class="btn btn-secondary">
968
- <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
969
- <path 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"/>
970
- </svg>
971
- Star on GitHub
972
- </a>
973
- </div>
974
- <div class="hero-stats">
975
- <div class="hero-stat">
976
- <div class="hero-stat-value">Zero</div>
977
- <div class="hero-stat-label">Configuration</div>
978
- </div>
979
- <div class="hero-stat">
980
- <div class="hero-stat-value">30 sec</div>
981
- <div class="hero-stat-label">Setup Time</div>
982
- </div>
983
- <div class="hero-stat">
984
- <div class="hero-stat-value">100%</div>
985
- <div class="hero-stat-label">Automatic</div>
986
- </div>
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
- <div class="hero-visual">
991
- <div class="bridge-diagram">
992
- <div class="bridge-row">
993
- <div class="bridge-box backend">
994
- <div class="bridge-icon">💎</div>
995
- <div class="bridge-label">Backend</div>
996
- <div class="bridge-title">Rails API</div>
997
- </div>
998
- <div class="bridge-connector">
999
- <svg width="40" height="24" viewBox="0 0 40 24" fill="none">
1000
- <path d="M0 12H40M32 4L40 12L32 20" stroke="currentColor" stroke-width="2"/>
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
- </div>
1003
- <div class="bridge-box center">
1004
- <div class="bridge-icon">🗺️</div>
1005
- <div class="bridge-label">Bridge</div>
1006
- <div class="bridge-title">RailsMap</div>
1007
- </div>
1008
- <div class="bridge-connector">
1009
- <svg width="40" height="24" viewBox="0 0 40 24" fill="none">
1010
- <path d="M0 12H40M32 4L40 12L32 20" stroke="currentColor" stroke-width="2"/>
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="bridge-box frontend">
1014
- <div class="bridge-icon">⚛️</div>
1015
- <div class="bridge-label">Frontend</div>
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
- </div>
1019
- <div class="bridge-items">
1020
- <div class="bridge-item">
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
- <div class="bridge-item">
1025
- <div class="bridge-item-icon">🎮</div>
1026
- <div class="bridge-item-text">Controllers</div>
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-item">
1029
- <div class="bridge-item-icon">📊</div>
1030
- <div class="bridge-item-text">Models</div>
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
- </div>
1036
- </section>
1037
-
1038
- <!-- Problem Section -->
1039
- <section class="problem" id="problem">
1040
- <div class="problem-content">
1041
- <span class="section-label">The Problem</span>
1042
- <h2 class="section-title">Sound familiar?</h2>
1043
- <p class="section-description">
1044
- Every Rails developer knows the pain. Your backend is powerful, but getting the frontend team on the same page feels impossible.
1045
- </p>
1046
- <div class="pain-points">
1047
- <div class="pain-point">
1048
- <div class="pain-point-icon">😩</div>
1049
- <h3>"What endpoints do we have?"</h3>
1050
- <p>Frontend devs constantly asking about available routes, required params, and response formats. You spend more time explaining than coding.</p>
1051
- </div>
1052
- <div class="pain-point">
1053
- <div class="pain-point-icon">📝</div>
1054
- <h3>Documentation is always outdated</h3>
1055
- <p>You wrote docs once, then the API changed. Now nobody trusts them, and you're back to Slack messages and screen shares.</p>
1056
- </div>
1057
- <div class="pain-point">
1058
- <div class="pain-point-icon">🔄</div>
1059
- <h3>Constant context switching</h3>
1060
- <p>Every time someone needs API info, you have to stop what you're doing, dig through controllers, and piece together the answer.</p>
1061
- </div>
1062
- <div class="pain-point">
1063
- <div class="pain-point-icon">🤷</div>
1064
- <h3>"What columns does this model have?"</h3>
1065
- <p>New team members struggle to understand your data structure. They open migration files, check schemas, ask questions...</p>
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
- </div>
1069
- </section>
1070
-
1071
- <!-- Solution Section -->
1072
- <section class="solution" id="features">
1073
- <div class="solution-header">
1074
- <span class="section-label">The Solution</span>
1075
- <h2 class="section-title">RailsMap does the work for you</h2>
1076
- <p class="section-description">
1077
- Install once, forget forever. Your API documentation stays in sync automatically.
1078
- </p>
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-card">
1092
- <div class="solution-card-icon">📊</div>
1093
- <h3>Model Introspection</h3>
1094
- <p>Database columns, associations, validations, and scopes are extracted automatically. Your data structure, documented without writing a single line.</p>
1095
- <div class="solution-card-features">
1096
- <span class="solution-card-feature">Columns & Types</span>
1097
- <span class="solution-card-feature">Associations</span>
1098
- <span class="solution-card-feature">Validations</span>
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
- </div>
1101
- <div class="solution-card">
1102
- <div class="solution-card-icon">🎨</div>
1103
- <h3>Beautiful Dark UI</h3>
1104
- <p>Modern, responsive interface that developers actually want to use. Searchable, filterable, and easy to navigate. Looks great on any device.</p>
1105
- <div class="solution-card-features">
1106
- <span class="solution-card-feature">Dark Theme</span>
1107
- <span class="solution-card-feature">Instant Search</span>
1108
- <span class="solution-card-feature">Responsive</span>
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
- </div>
1111
- <div class="solution-card">
1112
- <div class="solution-card-icon">🔒</div>
1113
- <h3>Environment-Based Auth</h3>
1114
- <p>Secure by default with environment variables. No database, no migrations—just set RAILS_MAP_USERNAME and RAILS_MAP_PASSWORD. Defaults to admin/password.</p>
1115
- <div class="solution-card-features">
1116
- <span class="solution-card-feature">No Database</span>
1117
- <span class="solution-card-feature">ENV Variables</span>
1118
- <span class="solution-card-feature">Default Credentials</span>
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
- </div>
1121
- <div class="solution-card">
1122
- <div class="solution-card-icon">⚡</div>
1123
- <h3>Zero Configuration</h3>
1124
- <p>Run one command. That's it. No config files, no annotations, no comments. RailsMap reads your code and generates docs automatically.</p>
1125
- <div class="solution-card-features">
1126
- <span class="solution-card-feature">One Command</span>
1127
- <span class="solution-card-feature">Auto-mount</span>
1128
- <span class="solution-card-feature">Works Instantly</span>
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
- </div>
1131
- <div class="solution-card">
1132
- <div class="solution-card-icon">🔄</div>
1133
- <h3>Always In Sync</h3>
1134
- <p>Add a route? It's documented. Change a model? Updated automatically. Your docs are always current because they come from your actual code.</p>
1135
- <div class="solution-card-features">
1136
- <span class="solution-card-feature">Live Updates</span>
1137
- <span class="solution-card-feature">No Manual Work</span>
1138
- <span class="solution-card-feature">Always Accurate</span>
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
- </div>
1141
- </div>
1142
- </section>
1143
-
1144
- <!-- Demo Section -->
1145
- <section class="demo">
1146
- <div class="demo-header">
1147
- <span class="section-label">Live Preview</span>
1148
- <h2 class="section-title">See what your team will see</h2>
1149
- <p class="section-description">
1150
- A clean, organized view of your entire Rails API. No more digging through code.
1151
- </p>
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
- <div class="demo-content">
1163
- <div class="demo-nav">
1164
- <span class="demo-nav-item active">Dashboard</span>
1165
- <span class="demo-nav-item">Routes</span>
1166
- <span class="demo-nav-item">Models</span>
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-stats">
1169
- <div class="demo-stat">
1170
- <div class="demo-stat-value">15</div>
1171
- <div class="demo-stat-label">Controllers</div>
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-stat">
1174
- <div class="demo-stat-value">67</div>
1175
- <div class="demo-stat-label">Routes</div>
1176
- </div>
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-card-meta">/api/v1/users · index, show, create, update, destroy</div>
1189
- </div>
1190
- <div class="demo-card">
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-card-meta">/api/v1/posts · index, show, create, update, destroy</div>
1196
- </div>
1197
- <div class="demo-card">
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-card">
1205
- <div class="demo-card-header">
1206
- <span class="demo-card-title">Post</span>
1207
- <span class="demo-card-badge">6 columns</span>
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
- </div>
1216
- </section>
1217
-
1218
- <!-- How it Works -->
1219
- <section class="how-it-works" id="how-it-works">
1220
- <div class="how-header">
1221
- <span class="section-label">Get Started</span>
1222
- <h2 class="section-title">Up and running in 30 seconds</h2>
1223
- <p class="section-description">
1224
- Seriously. Three commands and you're done.
1225
- </p>
1226
- </div>
1227
- <div class="steps">
1228
- <div class="step">
1229
- <div class="step-number">1</div>
1230
- <div class="step-content">
1231
- <h3>Add RailsMap to your Gemfile</h3>
1232
- <p>Just one line. That's all you need to add.</p>
1233
- <div class="step-code">
1234
- <span class="comment"># Gemfile</span><br>
1235
- <span class="keyword">gem</span> <span class="string">'rails_map'</span>
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
- </div>
1239
- <div class="step">
1240
- <div class="step-number">2</div>
1241
- <div class="step-content">
1242
- <h3>Run the install generator</h3>
1243
- <p>This mounts the engine and creates the config. Set environment variables to customize credentials (defaults: admin/password).</p>
1244
- <div class="step-code">
1245
- $ bundle install<br>
1246
- $ rails generate rails_map:install<br>
1247
- <span class="comment"># Optional: export RAILS_MAP_USERNAME=your_user</span><br>
1248
- <span class="comment"># Optional: export RAILS_MAP_PASSWORD=your_pass</span>
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
- </div>
1252
- <div class="step">
1253
- <div class="step-number">3</div>
1254
- <div class="step-content">
1255
- <h3>Visit your docs</h3>
1256
- <p>Start your server and open the documentation URL. Login with default credentials: <strong>admin/password</strong></p>
1257
- <div class="step-code">
1258
- $ rails server<br>
1259
- <span class="comment"># Open http://localhost:3000/api-doc</span><br>
1260
- <span class="comment"># Default: username=admin, password=password</span>
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
- </div>
1265
- </section>
1266
-
1267
- <!-- CTA -->
1268
- <section class="cta">
1269
- <div class="cta-content">
1270
- <h2>Stop explaining. Start shipping.</h2>
1271
- <p>
1272
- Give your team the documentation they need. Install RailsMap today and bridge the gap between backend and frontend—permanently.
1273
- </p>
1274
- <div class="cta-buttons">
1275
- <a href="https://rubygems.org/gems/rails_map" target="_blank" class="btn btn-primary">
1276
- Install RailsMap Free
1277
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1278
- <path d="M5 12h14M12 5l7 7-7 7"/>
1279
- </svg>
1280
- </a>
1281
- <a href="https://github.com/ArshdeepGrover/rails-map" target="_blank" class="btn btn-secondary">
1282
- View on GitHub
1283
- </a>
1284
- </div>
1285
- <div class="install-box">
1286
- <code>gem install rails_map</code>
1287
- <button class="copy-btn" onclick="copyToClipboard('gem install rails_map')">
1288
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1289
- <rect x="9" y="9" width="13" height="13" rx="2" ry="2"/>
1290
- <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
1291
- </svg>
1292
- </button>
1293
- </div>
1294
- </div>
1295
- </section>
1296
-
1297
- <!-- Footer -->
1298
- <footer class="footer">
1299
- <div class="footer-content">
1300
- <div class="footer-links">
1301
- <a href="https://github.com/ArshdeepGrover/rails-map" target="_blank">GitHub</a>
1302
- <a href="https://rubygems.org/gems/rails_map" target="_blank">RubyGems</a>
1303
- <a href="https://github.com/ArshdeepGrover/rails-map/issues" target="_blank">Issues</a>
1304
- <a href="https://github.com/ArshdeepGrover/rails-map/blob/main/CHANGELOG.md" target="_blank">Changelog</a>
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
- <div class="footer-copy">
1307
- Built with ❤️ by <a href="https://www.arshdeepsingh.info?utm_source=rails_map&utm_medium=footer&utm_campaign=developer_credit&utm_content=landing_page" target="_blank">Arshdeep Singh</a>
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
- </div>
1310
- </footer>
1311
-
1312
- <script>
1313
- function copyToClipboard(text) {
1314
- navigator.clipboard.writeText(text).then(() => {
1315
- const btn = document.querySelector('.copy-btn');
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
- setTimeout(() => {
1322
- btn.innerHTML = `
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
- }, 2000);
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
- // Smooth scroll
1333
- document.querySelectorAll('a[href^="#"]').forEach(anchor => {
1334
- anchor.addEventListener('click', function(e) {
1335
- e.preventDefault();
1336
- const target = document.querySelector(this.getAttribute('href'));
1337
- if (target) {
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>