create-gardener 2.0.9 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +328 -140
- package/package.json +1 -1
- package/template/src/backend/controllers/gardener/addPage.ts +25 -21
- package/template/src/backend/controllers/gardener/createStatic.ts +1 -0
- package/template/src/backend/libs/generateWebp.ts +0 -2
- package/template/src/frontend/static/cache/gardener_100x100.webp +0 -0
- package/template/src/frontend/static/components/copybtn.js +16 -3
- package/template/src/frontend/static/components/footer.js +33 -0
- package/template/src/frontend/static/components/gardener/errorBox.js +47 -0
- package/template/src/frontend/static/components/gardener/hotReloadbtn.js +82 -0
- package/template/src/frontend/static/components/gardener/pageOverlayBtn.js +138 -0
- package/template/src/frontend/static/components/gardener/parserWindow.js +159 -0
- package/template/src/frontend/static/components/nonui/api.js +15 -2
- package/template/src/frontend/static/gardener.js +129 -58
- package/template/src/frontend/static/gardenerDev.js +65 -399
- package/template/src/frontend/static/global.js +1 -1
- package/template/src/frontend/static/pages/pages._.js +5 -0
- package/template/src/frontend/static/style.css +101 -0
- package/template/src/frontend/static/style2.css +2 -2
- package/template/src/frontend/template/template._.ejs +121 -0
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
8
8
|
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
|
|
9
9
|
"Courier New", monospace;
|
|
10
|
+
--color-red-50: oklch(97.1% 0.013 17.38);
|
|
10
11
|
--color-red-300: oklch(80.8% 0.114 19.571);
|
|
12
|
+
--color-red-600: oklch(57.7% 0.245 27.325);
|
|
13
|
+
--color-red-700: oklch(50.5% 0.213 27.518);
|
|
11
14
|
--color-green-100: oklch(96.2% 0.044 156.743);
|
|
12
15
|
--color-green-200: oklch(92.5% 0.084 155.995);
|
|
13
16
|
--color-green-300: oklch(87.1% 0.15 154.449);
|
|
@@ -34,6 +37,7 @@
|
|
|
34
37
|
--color-slate-700: oklch(37.2% 0.044 257.287);
|
|
35
38
|
--color-slate-800: oklch(27.9% 0.041 260.031);
|
|
36
39
|
--color-slate-900: oklch(20.8% 0.042 265.755);
|
|
40
|
+
--color-gray-100: oklch(96.7% 0.003 264.542);
|
|
37
41
|
--color-gray-200: oklch(92.8% 0.006 264.531);
|
|
38
42
|
--color-gray-300: oklch(87.2% 0.01 258.338);
|
|
39
43
|
--color-gray-400: oklch(70.7% 0.022 261.325);
|
|
@@ -71,6 +75,7 @@
|
|
|
71
75
|
--font-weight-semibold: 600;
|
|
72
76
|
--font-weight-bold: 700;
|
|
73
77
|
--tracking-wide: 0.025em;
|
|
78
|
+
--tracking-wider: 0.05em;
|
|
74
79
|
--leading-relaxed: 1.625;
|
|
75
80
|
--radius-md: 0.375rem;
|
|
76
81
|
--radius-lg: 0.5rem;
|
|
@@ -248,6 +253,9 @@
|
|
|
248
253
|
.top-0 {
|
|
249
254
|
top: calc(var(--spacing) * 0);
|
|
250
255
|
}
|
|
256
|
+
.top-1\/2 {
|
|
257
|
+
top: calc(1 / 2 * 100%);
|
|
258
|
+
}
|
|
251
259
|
.top-1\/4 {
|
|
252
260
|
top: calc(1 / 4 * 100%);
|
|
253
261
|
}
|
|
@@ -281,6 +289,9 @@
|
|
|
281
289
|
.left-0 {
|
|
282
290
|
left: calc(var(--spacing) * 0);
|
|
283
291
|
}
|
|
292
|
+
.left-1\/2 {
|
|
293
|
+
left: calc(1 / 2 * 100%);
|
|
294
|
+
}
|
|
284
295
|
.left-1\/4 {
|
|
285
296
|
left: calc(1 / 4 * 100%);
|
|
286
297
|
}
|
|
@@ -302,6 +313,9 @@
|
|
|
302
313
|
.z-100 {
|
|
303
314
|
z-index: 100;
|
|
304
315
|
}
|
|
316
|
+
.z-\[100\] {
|
|
317
|
+
z-index: 100;
|
|
318
|
+
}
|
|
305
319
|
.container {
|
|
306
320
|
width: 100%;
|
|
307
321
|
@media (width >= 40rem) {
|
|
@@ -335,6 +349,9 @@
|
|
|
335
349
|
.mt-2 {
|
|
336
350
|
margin-top: calc(var(--spacing) * 2);
|
|
337
351
|
}
|
|
352
|
+
.mt-4 {
|
|
353
|
+
margin-top: calc(var(--spacing) * 4);
|
|
354
|
+
}
|
|
338
355
|
.mt-6 {
|
|
339
356
|
margin-top: calc(var(--spacing) * 6);
|
|
340
357
|
}
|
|
@@ -401,6 +418,9 @@
|
|
|
401
418
|
.w-5 {
|
|
402
419
|
width: calc(var(--spacing) * 5);
|
|
403
420
|
}
|
|
421
|
+
.w-11\/12 {
|
|
422
|
+
width: calc(11 / 12 * 100%);
|
|
423
|
+
}
|
|
404
424
|
.w-14 {
|
|
405
425
|
width: calc(var(--spacing) * 14);
|
|
406
426
|
}
|
|
@@ -434,6 +454,14 @@
|
|
|
434
454
|
.flex-1 {
|
|
435
455
|
flex: 1;
|
|
436
456
|
}
|
|
457
|
+
.-translate-x-1\/2 {
|
|
458
|
+
--tw-translate-x: calc(calc(1 / 2 * 100%) * -1);
|
|
459
|
+
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
460
|
+
}
|
|
461
|
+
.-translate-y-1\/2 {
|
|
462
|
+
--tw-translate-y: calc(calc(1 / 2 * 100%) * -1);
|
|
463
|
+
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
464
|
+
}
|
|
437
465
|
.transform {
|
|
438
466
|
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
|
|
439
467
|
}
|
|
@@ -480,6 +508,9 @@
|
|
|
480
508
|
margin-block-end: calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)));
|
|
481
509
|
}
|
|
482
510
|
}
|
|
511
|
+
.overflow-hidden {
|
|
512
|
+
overflow: hidden;
|
|
513
|
+
}
|
|
483
514
|
.overflow-scroll {
|
|
484
515
|
overflow: scroll;
|
|
485
516
|
}
|
|
@@ -508,6 +539,10 @@
|
|
|
508
539
|
border-top-left-radius: var(--radius-lg);
|
|
509
540
|
border-top-right-radius: var(--radius-lg);
|
|
510
541
|
}
|
|
542
|
+
.rounded-r-lg {
|
|
543
|
+
border-top-right-radius: var(--radius-lg);
|
|
544
|
+
border-bottom-right-radius: var(--radius-lg);
|
|
545
|
+
}
|
|
511
546
|
.border {
|
|
512
547
|
border-style: var(--tw-border-style);
|
|
513
548
|
border-width: 1px;
|
|
@@ -524,9 +559,16 @@
|
|
|
524
559
|
border-bottom-style: var(--tw-border-style);
|
|
525
560
|
border-bottom-width: 1px;
|
|
526
561
|
}
|
|
562
|
+
.border-l-8 {
|
|
563
|
+
border-left-style: var(--tw-border-style);
|
|
564
|
+
border-left-width: 8px;
|
|
565
|
+
}
|
|
527
566
|
.border-black {
|
|
528
567
|
border-color: var(--color-black);
|
|
529
568
|
}
|
|
569
|
+
.border-gray-200 {
|
|
570
|
+
border-color: var(--color-gray-200);
|
|
571
|
+
}
|
|
530
572
|
.border-gray-700 {
|
|
531
573
|
border-color: var(--color-gray-700);
|
|
532
574
|
}
|
|
@@ -539,6 +581,9 @@
|
|
|
539
581
|
.border-green-700 {
|
|
540
582
|
border-color: var(--color-green-700);
|
|
541
583
|
}
|
|
584
|
+
.border-red-600 {
|
|
585
|
+
border-color: var(--color-red-600);
|
|
586
|
+
}
|
|
542
587
|
.border-slate-700 {
|
|
543
588
|
border-color: var(--color-slate-700);
|
|
544
589
|
}
|
|
@@ -560,6 +605,9 @@
|
|
|
560
605
|
.bg-blue-500 {
|
|
561
606
|
background-color: var(--color-blue-500);
|
|
562
607
|
}
|
|
608
|
+
.bg-gray-100 {
|
|
609
|
+
background-color: var(--color-gray-100);
|
|
610
|
+
}
|
|
563
611
|
.bg-gray-200 {
|
|
564
612
|
background-color: var(--color-gray-200);
|
|
565
613
|
}
|
|
@@ -581,6 +629,9 @@
|
|
|
581
629
|
.bg-green-900 {
|
|
582
630
|
background-color: var(--color-green-900);
|
|
583
631
|
}
|
|
632
|
+
.bg-red-50 {
|
|
633
|
+
background-color: var(--color-red-50);
|
|
634
|
+
}
|
|
584
635
|
.bg-red-300 {
|
|
585
636
|
background-color: var(--color-red-300);
|
|
586
637
|
}
|
|
@@ -599,6 +650,9 @@
|
|
|
599
650
|
.object-contain {
|
|
600
651
|
object-fit: contain;
|
|
601
652
|
}
|
|
653
|
+
.p-0 {
|
|
654
|
+
padding: calc(var(--spacing) * 0);
|
|
655
|
+
}
|
|
602
656
|
.p-2 {
|
|
603
657
|
padding: calc(var(--spacing) * 2);
|
|
604
658
|
}
|
|
@@ -693,6 +747,13 @@
|
|
|
693
747
|
--tw-tracking: var(--tracking-wide);
|
|
694
748
|
letter-spacing: var(--tracking-wide);
|
|
695
749
|
}
|
|
750
|
+
.tracking-wider {
|
|
751
|
+
--tw-tracking: var(--tracking-wider);
|
|
752
|
+
letter-spacing: var(--tracking-wider);
|
|
753
|
+
}
|
|
754
|
+
.break-words {
|
|
755
|
+
overflow-wrap: break-word;
|
|
756
|
+
}
|
|
696
757
|
.text-black {
|
|
697
758
|
color: var(--color-black);
|
|
698
759
|
}
|
|
@@ -708,6 +769,9 @@
|
|
|
708
769
|
.text-gray-400 {
|
|
709
770
|
color: var(--color-gray-400);
|
|
710
771
|
}
|
|
772
|
+
.text-gray-800 {
|
|
773
|
+
color: var(--color-gray-800);
|
|
774
|
+
}
|
|
711
775
|
.text-green-100 {
|
|
712
776
|
color: var(--color-green-100);
|
|
713
777
|
}
|
|
@@ -726,6 +790,9 @@
|
|
|
726
790
|
.text-green-900 {
|
|
727
791
|
color: var(--color-green-900);
|
|
728
792
|
}
|
|
793
|
+
.text-red-700 {
|
|
794
|
+
color: var(--color-red-700);
|
|
795
|
+
}
|
|
729
796
|
.text-slate-500 {
|
|
730
797
|
color: var(--color-slate-500);
|
|
731
798
|
}
|
|
@@ -753,6 +820,10 @@
|
|
|
753
820
|
.opacity-70 {
|
|
754
821
|
opacity: 70%;
|
|
755
822
|
}
|
|
823
|
+
.shadow-2xl {
|
|
824
|
+
--tw-shadow: 0 25px 50px -12px var(--tw-shadow-color, rgb(0 0 0 / 0.25));
|
|
825
|
+
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
826
|
+
}
|
|
756
827
|
.shadow-lg {
|
|
757
828
|
--tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
|
758
829
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
@@ -780,6 +851,11 @@
|
|
|
780
851
|
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
|
781
852
|
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
|
782
853
|
}
|
|
854
|
+
.transition-colors {
|
|
855
|
+
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;
|
|
856
|
+
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
|
857
|
+
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
|
858
|
+
}
|
|
783
859
|
.duration-200 {
|
|
784
860
|
--tw-duration: 200ms;
|
|
785
861
|
transition-duration: 200ms;
|
|
@@ -788,6 +864,13 @@
|
|
|
788
864
|
-webkit-user-select: all;
|
|
789
865
|
user-select: all;
|
|
790
866
|
}
|
|
867
|
+
.hover\:bg-black {
|
|
868
|
+
&:hover {
|
|
869
|
+
@media (hover: hover) {
|
|
870
|
+
background-color: var(--color-black);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
}
|
|
791
874
|
.hover\:bg-blue-600 {
|
|
792
875
|
&:hover {
|
|
793
876
|
@media (hover: hover) {
|
|
@@ -856,6 +939,21 @@
|
|
|
856
939
|
}
|
|
857
940
|
}
|
|
858
941
|
}
|
|
942
|
+
@property --tw-translate-x {
|
|
943
|
+
syntax: "*";
|
|
944
|
+
inherits: false;
|
|
945
|
+
initial-value: 0;
|
|
946
|
+
}
|
|
947
|
+
@property --tw-translate-y {
|
|
948
|
+
syntax: "*";
|
|
949
|
+
inherits: false;
|
|
950
|
+
initial-value: 0;
|
|
951
|
+
}
|
|
952
|
+
@property --tw-translate-z {
|
|
953
|
+
syntax: "*";
|
|
954
|
+
inherits: false;
|
|
955
|
+
initial-value: 0;
|
|
956
|
+
}
|
|
859
957
|
@property --tw-rotate-x {
|
|
860
958
|
syntax: "*";
|
|
861
959
|
inherits: false;
|
|
@@ -1017,6 +1115,9 @@
|
|
|
1017
1115
|
@layer properties {
|
|
1018
1116
|
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
|
|
1019
1117
|
*, ::before, ::after, ::backdrop {
|
|
1118
|
+
--tw-translate-x: 0;
|
|
1119
|
+
--tw-translate-y: 0;
|
|
1120
|
+
--tw-translate-z: 0;
|
|
1020
1121
|
--tw-rotate-x: initial;
|
|
1021
1122
|
--tw-rotate-y: initial;
|
|
1022
1123
|
--tw-rotate-z: initial;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<link rel="icon" type="image/svg+xml" href="/static/cache/favicon_50x50.webp" />
|
|
7
|
+
<link href="/static/style.css" rel="stylesheet"/>
|
|
8
|
+
<link href="/static/style2.css" rel="stylesheet"/>
|
|
9
|
+
<title>Gardener: The Mini Web Framework</title>
|
|
10
|
+
</head>
|
|
11
|
+
<body class="bg-slate-50 text-slate-900 font-sans">
|
|
12
|
+
|
|
13
|
+
<div class='hidden' id='fileName'><%=fileName%></div>
|
|
14
|
+
<div class='loader w-screen h-screen bg-white fixed z-2'> </div>
|
|
15
|
+
<div class='notification'></div>
|
|
16
|
+
|
|
17
|
+
<div id='main'>
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
<!-- hero -->
|
|
21
|
+
<div class='hero flex-wrap w-full h-screen bg-green-200 flex justify-center items-center px-10'>
|
|
22
|
+
<div class='w-200'>
|
|
23
|
+
<a href="https://ritish.site">Home</a> > <a href="https://ritish.site/projects">Projects</a> > <a href="/">Gardener</a>
|
|
24
|
+
<h1 class='text-6xl my-10 font-bold text-green-900'>Gardener</h1>
|
|
25
|
+
<h2 class='text-2xl font-bold text-green-800 mb-4'>Develop With No Bloat</h2>
|
|
26
|
+
<p class="text-lg mb-6 max-w-md">Gardener is a lightweight, DOM-first front-end library. No virtual DOM, no JSX, and no compilation step. Just the real DOM.</p>
|
|
27
|
+
<div class='flex gap-2 m-2'>
|
|
28
|
+
<a class="block bg-green-700 text-white px-8 py-3 rounded-lg font-bold hover:bg-green-800 transition" href='/get-started'>Get Started</a>
|
|
29
|
+
<a class="block border border-green-700 text-black px-8 py-3 rounded-lg font-bold hover:text-white hover:bg-green-800 transition" href='/documentation/#introduction'>Documentation</a>
|
|
30
|
+
</div>
|
|
31
|
+
<div class='flex gap-2 m-2'>
|
|
32
|
+
<a class="block border border-green-700 text-black px-8 py-3 rounded-lg font-bold hover:text-white hover:bg-green-800 transition" href='https://github.com/ritishDas/Gardener'>View On Github</a>
|
|
33
|
+
<a class="block border border-green-700 text-black px-8 py-3 rounded-lg font-bold hover:text-white hover:bg-green-800 transition" href='https://www.npmjs.com/package/create-gardener'>View On npm</a>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
<img src="/static/cache/gardener_500x500.webp" alt="Gardener Logo" class="w-96 h-96 object-contain ml-10">
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<!-- Copy command -->
|
|
40
|
+
<div class="flex w-1/4 items-center mx-auto my-15 justify-between gap-4 bg-[#1e1e1e] border border-gray-700 rounded-lg px-4 py-3 font-mono shadow-sm group">
|
|
41
|
+
<span class="text-sm md:text-base text-gray-300 select-all">
|
|
42
|
+
<span class="text-emerald-400 mr-2">$</span><span class='initCommand'>pnpm create gardener app</span>
|
|
43
|
+
</span>
|
|
44
|
+
|
|
45
|
+
<button class="copybtn flex items-center justify-center p-2 text-gray-400 hover:text-white hover:bg-white/10 rounded transition-all duration-200 active:scale-95" title="Copy to clipboard">
|
|
46
|
+
<span class="w-5 h-5" >
|
|
47
|
+
<%- include('partials/icons/clipboard') %>
|
|
48
|
+
</span>
|
|
49
|
+
</button>
|
|
50
|
+
</div>
|
|
51
|
+
<!-- Philosophy -->
|
|
52
|
+
<div class="max-w-5xl mx-auto py-20 px-6 grid md:grid-cols-2 gap-12">
|
|
53
|
+
<div>
|
|
54
|
+
<h3 class="text-3xl font-bold mb-4 text-green-900">✨ Philosophy</h3>
|
|
55
|
+
<ul class="space-y-3 text-slate-700">
|
|
56
|
+
<li><strong>DOM-First:</strong> Renders directly to the real DOM.</li>
|
|
57
|
+
<li><strong>Deterministic:</strong> If you can inspect it, you can understand it.</li>
|
|
58
|
+
<li><strong>Native:</strong> Works in the browser via ES modules.</li>
|
|
59
|
+
<li><strong>Zero Build:</strong> No bundlers or magic required.</li>
|
|
60
|
+
</ul>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<!-- Features -->
|
|
64
|
+
<div>
|
|
65
|
+
<h3 class="text-3xl font-bold mb-4 text-green-900">🚀 Features</h3>
|
|
66
|
+
<div class="grid grid-cols-2 gap-4">
|
|
67
|
+
<div class="p-4 bg-white shadow-sm border border-green-100 rounded">Declarative UI</div>
|
|
68
|
+
<div class="p-4 bg-white shadow-sm border border-green-100 rounded">SVG Namespace Support</div>
|
|
69
|
+
<div class="p-4 bg-white shadow-sm border border-green-100 rounded">Hot Reload</div>
|
|
70
|
+
<div class="p-4 bg-white shadow-sm border border-green-100 rounded">Image Optimization</div>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<!-- Api Example -->
|
|
76
|
+
<div class="bg-slate-900 py-20 text-white">
|
|
77
|
+
<div class="max-w-5xl mx-auto px-6">
|
|
78
|
+
<h3 class="text-3xl font-bold mb-8 text-center text-green-400">The Core API</h3>
|
|
79
|
+
<div class="bg-slate-800 p-6 rounded-xl border border-slate-700 font-mono text-sm overflow-x-auto">
|
|
80
|
+
<pre class="text-blue-300">
|
|
81
|
+
gardener({
|
|
82
|
+
t: <span class="text-green-300">'div'</span>,
|
|
83
|
+
cn: [<span class="text-green-300">'p-6'</span>, <span class="text-green-300">'flex'</span>],
|
|
84
|
+
attr: { id: <span class="text-green-300">'hero'</span> },
|
|
85
|
+
txt: <span class="text-green-300">'Welcome to the Garden'</span>,
|
|
86
|
+
events: {
|
|
87
|
+
click: () => console.log(<span class="text-green-300">'Growth!'</span>)
|
|
88
|
+
},
|
|
89
|
+
children: [
|
|
90
|
+
{ t: <span class="text-green-300">'span'</span>, txt: <span class="text-green-300">'Pure DOM nodes.'</span> }
|
|
91
|
+
]
|
|
92
|
+
})
|
|
93
|
+
</pre>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<div class="max-w-5xl mx-auto py-20 px-6 text-center">
|
|
99
|
+
<h3 class="text-3xl font-bold mb-4 text-green-900">🧠 Simple State</h3>
|
|
100
|
+
<p class="mb-8 text-slate-600">No proxies. No diffing. Just clean, reactive callbacks.</p>
|
|
101
|
+
<div class="inline-block text-left bg-white p-6 rounded shadow-lg border-t-4 border-green-500 font-mono text-sm">
|
|
102
|
+
<p class="text-slate-500">// Initialize</p>
|
|
103
|
+
<p>const count = new State(0);</p>
|
|
104
|
+
<p class="text-slate-500 mt-2">// React</p>
|
|
105
|
+
<p>count.registerCb(val => updateUI(val));</p>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
<!-- Footer -->
|
|
110
|
+
<footer class="bg-green-900 text-green-100 py-12 text-center">
|
|
111
|
+
<p class="text-xl italic">"Because sometimes you don't need a forest. Just a garden."</p>
|
|
112
|
+
<div class="mt-6 text-sm opacity-70">
|
|
113
|
+
MIT Licensed | Built on Express & EJS
|
|
114
|
+
</div>
|
|
115
|
+
</footer>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
</body>
|
|
119
|
+
<script type='module' src='/static/global.js'> </script>
|
|
120
|
+
|
|
121
|
+
</html>
|