pushing for review
This commit is contained in:
parent
620b4b3de4
commit
b1d7569150
19 changed files with 3742 additions and 228 deletions
3239
Cargo.lock
generated
3239
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -9,6 +9,8 @@ edition = "2021"
|
||||||
anyhow = "1.0.79"
|
anyhow = "1.0.79"
|
||||||
askama = "0.12.1"
|
askama = "0.12.1"
|
||||||
axum = "0.7.4"
|
axum = "0.7.4"
|
||||||
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
|
surrealdb = { version = "1.2.0", features = ["kv-speedb"] }
|
||||||
tokio = { version = "1.36.0", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1.36.0", features = ["macros", "rt-multi-thread"] }
|
||||||
tower = "0.4.13"
|
tower = "0.4.13"
|
||||||
tower-http = { version = "0.5.1", features = ["fs"] }
|
tower-http = { version = "0.5.1", features = ["fs"] }
|
||||||
|
|
|
||||||
BIN
assets/SK-test-logo.png
Normal file
BIN
assets/SK-test-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 129 KiB |
BIN
assets/aocollapse.png
Normal file
BIN
assets/aocollapse.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
324
assets/main.css
324
assets/main.css
|
|
@ -767,6 +767,16 @@ select {
|
||||||
inset: -0.125rem;
|
inset: -0.125rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.-inset-x-4 {
|
||||||
|
left: -1rem;
|
||||||
|
right: -1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.-inset-y-6 {
|
||||||
|
top: -1.5rem;
|
||||||
|
bottom: -1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.inset-y-0 {
|
.inset-y-0 {
|
||||||
top: 0px;
|
top: 0px;
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
|
|
@ -776,12 +786,21 @@ select {
|
||||||
left: 0px;
|
left: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-4 {
|
.z-0 {
|
||||||
left: 1rem;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-4 {
|
.z-10 {
|
||||||
top: 1rem;
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-20 {
|
||||||
|
z-index: 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx-4 {
|
||||||
|
margin-left: 1rem;
|
||||||
|
margin-right: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx-72 {
|
.mx-72 {
|
||||||
|
|
@ -794,12 +813,36 @@ select {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.-mb-8 {
|
.mb-24 {
|
||||||
margin-bottom: -2rem;
|
margin-bottom: 6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.-ml-px {
|
.ml-2 {
|
||||||
margin-left: -1px;
|
margin-left: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-4 {
|
||||||
|
margin-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr-12 {
|
||||||
|
margin-right: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-12 {
|
||||||
|
margin-top: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-2 {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-4 {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-6 {
|
||||||
|
margin-top: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.block {
|
.block {
|
||||||
|
|
@ -814,14 +857,18 @@ select {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flow-root {
|
.grid {
|
||||||
display: flow-root;
|
display: grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.h-12 {
|
||||||
|
height: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
.h-16 {
|
.h-16 {
|
||||||
height: 4rem;
|
height: 4rem;
|
||||||
}
|
}
|
||||||
|
|
@ -830,42 +877,22 @@ select {
|
||||||
height: 1.5rem;
|
height: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.h-5 {
|
|
||||||
height: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-8 {
|
.h-8 {
|
||||||
height: 2rem;
|
height: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.h-full {
|
.w-12 {
|
||||||
height: 100%;
|
width: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.w-6 {
|
.w-6 {
|
||||||
width: 1.5rem;
|
width: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.w-0 {
|
|
||||||
width: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w-0\.5 {
|
|
||||||
width: 0.125rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w-5 {
|
|
||||||
width: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w-8 {
|
.w-8 {
|
||||||
width: 2rem;
|
width: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.min-w-0 {
|
|
||||||
min-width: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.max-w-7xl {
|
.max-w-7xl {
|
||||||
max-width: 80rem;
|
max-width: 80rem;
|
||||||
}
|
}
|
||||||
|
|
@ -874,6 +901,32 @@ select {
|
||||||
flex: 1 1 0%;
|
flex: 1 1 0%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex-none {
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scale-95 {
|
||||||
|
--tw-scale-x: .95;
|
||||||
|
--tw-scale-y: .95;
|
||||||
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-cols-1 {
|
||||||
|
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-cols-3 {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-col {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items-start {
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
.items-center {
|
.items-center {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
@ -886,6 +939,19 @@ select {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.gap-4 {
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-x-12 {
|
||||||
|
-moz-column-gap: 3rem;
|
||||||
|
column-gap: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-y-16 {
|
||||||
|
row-gap: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
.space-x-4 > :not([hidden]) ~ :not([hidden]) {
|
.space-x-4 > :not([hidden]) ~ :not([hidden]) {
|
||||||
--tw-space-x-reverse: 0;
|
--tw-space-x-reverse: 0;
|
||||||
margin-right: calc(1rem * var(--tw-space-x-reverse));
|
margin-right: calc(1rem * var(--tw-space-x-reverse));
|
||||||
|
|
@ -898,62 +964,42 @@ select {
|
||||||
margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));
|
margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));
|
||||||
}
|
}
|
||||||
|
|
||||||
.space-x-3 > :not([hidden]) ~ :not([hidden]) {
|
.rounded-full {
|
||||||
--tw-space-x-reverse: 0;
|
border-radius: 9999px;
|
||||||
margin-right: calc(0.75rem * var(--tw-space-x-reverse));
|
|
||||||
margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
|
|
||||||
}
|
|
||||||
|
|
||||||
.whitespace-nowrap {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.rounded-md {
|
.rounded-md {
|
||||||
border-radius: 0.375rem;
|
border-radius: 0.375rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rounded-full {
|
|
||||||
border-radius: 9999px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-gray-900 {
|
.bg-gray-900 {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(17 24 39 / var(--tw-bg-opacity));
|
background-color: rgb(17 24 39 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-stone-200 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(231 229 228 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.bg-stone-400 {
|
.bg-stone-400 {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(168 162 158 / var(--tw-bg-opacity));
|
background-color: rgb(168 162 158 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-stone-800 {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(41 37 36 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-stone-900 {
|
.bg-stone-900 {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(28 25 23 / var(--tw-bg-opacity));
|
background-color: rgb(28 25 23 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-blue-500 {
|
.bg-white {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(59 130 246 / var(--tw-bg-opacity));
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-gray-200 {
|
.bg-zinc-50 {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
|
background-color: rgb(250 250 250 / var(--tw-bg-opacity));
|
||||||
}
|
|
||||||
|
|
||||||
.bg-gray-400 {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(156 163 175 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-green-500 {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(34 197 94 / var(--tw-bg-opacity));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-2 {
|
.p-2 {
|
||||||
|
|
@ -979,10 +1025,18 @@ select {
|
||||||
padding-bottom: 0.75rem;
|
padding-bottom: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pb-4 {
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.pb-6 {
|
.pb-6 {
|
||||||
padding-bottom: 1.5rem;
|
padding-bottom: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pt-12 {
|
||||||
|
padding-top: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
.pt-2 {
|
.pt-2 {
|
||||||
padding-top: 0.5rem;
|
padding-top: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
@ -991,22 +1045,19 @@ select {
|
||||||
padding-top: 1.5rem;
|
padding-top: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pb-8 {
|
.text-center {
|
||||||
padding-bottom: 2rem;
|
text-align: center;
|
||||||
}
|
|
||||||
|
|
||||||
.pt-1 {
|
|
||||||
padding-top: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pt-1\.5 {
|
|
||||||
padding-top: 0.375rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-right {
|
.text-right {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-2xl {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
line-height: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
.text-4xl {
|
.text-4xl {
|
||||||
font-size: 2.25rem;
|
font-size: 2.25rem;
|
||||||
line-height: 2.5rem;
|
line-height: 2.5rem;
|
||||||
|
|
@ -1022,6 +1073,10 @@ select {
|
||||||
line-height: 1.25rem;
|
line-height: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.font-bold {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
.font-extrabold {
|
.font-extrabold {
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
@ -1030,6 +1085,15 @@ select {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.font-semibold {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-emerald-300 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(110 231 183 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.text-gray-300 {
|
.text-gray-300 {
|
||||||
--tw-text-opacity: 1;
|
--tw-text-opacity: 1;
|
||||||
color: rgb(209 213 219 / var(--tw-text-opacity));
|
color: rgb(209 213 219 / var(--tw-text-opacity));
|
||||||
|
|
@ -1060,25 +1124,42 @@ select {
|
||||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-gray-500 {
|
.text-zinc-800 {
|
||||||
--tw-text-opacity: 1;
|
--tw-text-opacity: 1;
|
||||||
color: rgb(107 114 128 / var(--tw-text-opacity));
|
color: rgb(39 39 42 / var(--tw-text-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-gray-900 {
|
.opacity-0 {
|
||||||
--tw-text-opacity: 1;
|
opacity: 0;
|
||||||
color: rgb(17 24 39 / var(--tw-text-opacity));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ring-8 {
|
.shadow-md {
|
||||||
|
--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||||
|
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadow-zinc-800\/5 {
|
||||||
|
--tw-shadow-color: rgb(39 39 42 / 0.05);
|
||||||
|
--tw-shadow: var(--tw-shadow-colored);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ring-1 {
|
||||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(8px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ring-white {
|
.ring-zinc-900\/5 {
|
||||||
--tw-ring-opacity: 1;
|
--tw-ring-color: rgb(24 24 27 / 0.05);
|
||||||
--tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity));
|
}
|
||||||
|
|
||||||
|
.transition {
|
||||||
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
|
||||||
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
|
||||||
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
|
||||||
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
transition-duration: 150ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hover\:bg-gray-700:hover {
|
.hover\:bg-gray-700:hover {
|
||||||
|
|
@ -1086,6 +1167,11 @@ select {
|
||||||
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
|
background-color: rgb(55 65 81 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hover\:bg-stone-300:hover {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(214 211 209 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.hover\:bg-stone-700:hover {
|
.hover\:bg-stone-700:hover {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(68 64 60 / var(--tw-bg-opacity));
|
background-color: rgb(68 64 60 / var(--tw-bg-opacity));
|
||||||
|
|
@ -1116,7 +1202,27 @@ select {
|
||||||
--tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity));
|
--tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.group:hover .group-hover\:scale-100 {
|
||||||
|
--tw-scale-x: 1;
|
||||||
|
--tw-scale-y: 1;
|
||||||
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||||
|
}
|
||||||
|
|
||||||
|
.group:hover .group-hover\:text-emerald-500 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(16 185 129 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.group:hover .group-hover\:opacity-100 {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 640px) {
|
@media (min-width: 640px) {
|
||||||
|
.sm\:-inset-x-6 {
|
||||||
|
left: -1.5rem;
|
||||||
|
right: -1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.sm\:ml-6 {
|
.sm\:ml-6 {
|
||||||
margin-left: 1.5rem;
|
margin-left: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
@ -1129,6 +1235,10 @@ select {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sm\:grid-cols-2 {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
.sm\:items-stretch {
|
.sm\:items-stretch {
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
@ -1137,6 +1247,10 @@ select {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sm\:rounded-2xl {
|
||||||
|
border-radius: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.sm\:px-6 {
|
.sm\:px-6 {
|
||||||
padding-left: 1.5rem;
|
padding-left: 1.5rem;
|
||||||
padding-right: 1.5rem;
|
padding-right: 1.5rem;
|
||||||
|
|
@ -1144,8 +1258,52 @@ select {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
|
.lg\:grid-cols-3 {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
.lg\:px-8 {
|
.lg\:px-8 {
|
||||||
padding-left: 2rem;
|
padding-left: 2rem;
|
||||||
padding-right: 2rem;
|
padding-right: 2rem;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.dark\:border {
|
||||||
|
border-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:border-zinc-700\/50 {
|
||||||
|
border-color: rgb(63 63 70 / 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:bg-zinc-800 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(39 39 42 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:bg-zinc-800\/50 {
|
||||||
|
background-color: rgb(39 39 42 / 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:text-emerald-700 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(4 120 87 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:text-stone-100 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(245 245 244 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:text-zinc-100 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(244 244 245 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark\:ring-0 {
|
||||||
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||||
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
BIN
assets/sk-extract.png
Normal file
BIN
assets/sk-extract.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 588 B |
BIN
assets/sunserver.png
Normal file
BIN
assets/sunserver.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4 KiB |
|
|
@ -5,6 +5,8 @@ pkgs.rustPlatform.buildRustPackage rec {
|
||||||
version = "1.0.0";
|
version = "1.0.0";
|
||||||
cargoLock.lockFile = ../Cargo.lock;
|
cargoLock.lockFile = ../Cargo.lock;
|
||||||
src = pkgs.lib.cleanSource ../.;
|
src = pkgs.lib.cleanSource ../.;
|
||||||
buildInputs = [ ];
|
buildInputs = with pkgs; [
|
||||||
|
surrealdb
|
||||||
|
];
|
||||||
# doCheck = false;
|
# doCheck = false;
|
||||||
}
|
}
|
||||||
|
|
@ -1,17 +1,26 @@
|
||||||
{ pkgs ? import <nixpkgs> { } }:
|
{ pkgs ? import <nixpkgs> { } }:
|
||||||
pkgs.mkShell {
|
let
|
||||||
# Get dependencies from the main package
|
runtimeLibs = [
|
||||||
inputsFrom = [ (pkgs.callPackage ./default.nix { }) ];
|
pkgs.libclang
|
||||||
# Additional tooling
|
pkgs.rocksdb
|
||||||
buildInputs = with pkgs; [
|
|
||||||
cargo
|
|
||||||
cargo-watch
|
|
||||||
rustc
|
|
||||||
rustup
|
|
||||||
clippy
|
|
||||||
rust-analyzer
|
|
||||||
pkg-config
|
|
||||||
bacon
|
|
||||||
nodePackages_latest.pnpm
|
|
||||||
];
|
];
|
||||||
}
|
in
|
||||||
|
pkgs.mkShell {
|
||||||
|
# Get dependencies from the main package
|
||||||
|
inputsFrom = [ (pkgs.callPackage ./default.nix { }) ];
|
||||||
|
# Additional tooling
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
cargo
|
||||||
|
cargo-watch
|
||||||
|
rustc
|
||||||
|
rustup
|
||||||
|
clippy
|
||||||
|
rust-analyzer
|
||||||
|
pkg-config
|
||||||
|
bacon
|
||||||
|
nodePackages_latest.pnpm
|
||||||
|
surrealdb
|
||||||
|
libclang
|
||||||
|
];
|
||||||
|
LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath runtimeLibs}";
|
||||||
|
}
|
||||||
|
|
|
||||||
27
src/handlers.rs
Normal file
27
src/handlers.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
use super::templates;
|
||||||
|
use axum::response::IntoResponse;
|
||||||
|
|
||||||
|
pub async fn blog_post() -> impl IntoResponse {
|
||||||
|
let template = templates::PostTemplate {
|
||||||
|
title:"Test Tile".to_string(),
|
||||||
|
description:"this is a test description of a test blog post for rendering in its post template".to_string(),
|
||||||
|
post_date:"02/21/2024".to_string()
|
||||||
|
};
|
||||||
|
templates::HtmlTemplate(template)
|
||||||
|
}
|
||||||
|
pub async fn root() -> impl IntoResponse {
|
||||||
|
let template = templates::HomeTemplate {};
|
||||||
|
templates::HtmlTemplate(template)
|
||||||
|
}
|
||||||
|
pub async fn blog() -> impl IntoResponse {
|
||||||
|
let template = templates::BlogTemplate {};
|
||||||
|
templates::HtmlTemplate(template)
|
||||||
|
}
|
||||||
|
pub async fn resume() -> impl IntoResponse {
|
||||||
|
let template = templates::ResumeTemplate {};
|
||||||
|
templates::HtmlTemplate(template)
|
||||||
|
}
|
||||||
|
pub async fn projects() -> impl IntoResponse {
|
||||||
|
let template = templates::ProjectsTemplate {};
|
||||||
|
templates::HtmlTemplate(template)
|
||||||
|
}
|
||||||
92
src/main.rs
92
src/main.rs
|
|
@ -1,18 +1,23 @@
|
||||||
use askama::Template;
|
|
||||||
use axum::{
|
|
||||||
http::StatusCode,
|
|
||||||
response::{Html, IntoResponse, Response},
|
|
||||||
routing::get,
|
|
||||||
Router,
|
|
||||||
};
|
|
||||||
use tower_http::services::ServeDir;
|
use tower_http::services::ServeDir;
|
||||||
use tracing::info;
|
use std::env;
|
||||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||||
|
|
||||||
|
mod router;
|
||||||
|
mod handlers;
|
||||||
|
mod templates;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let assets_path = std::env::current_dir().unwrap();
|
setup_tracing();
|
||||||
|
|
||||||
|
let assets_path = env::current_dir().unwrap().join("assets");
|
||||||
|
let app = router::router(&assets_path);
|
||||||
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||||
|
axum::serve(listener, app).await.unwrap();
|
||||||
|
println!("Listening on port 3000");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_tracing(){
|
||||||
tracing_subscriber::registry()
|
tracing_subscriber::registry()
|
||||||
.with(
|
.with(
|
||||||
tracing_subscriber::EnvFilter::try_from_default_env()
|
tracing_subscriber::EnvFilter::try_from_default_env()
|
||||||
|
|
@ -20,71 +25,6 @@ async fn main() {
|
||||||
)
|
)
|
||||||
.with(tracing_subscriber::fmt::layer())
|
.with(tracing_subscriber::fmt::layer())
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
info!("hello, web server!");
|
|
||||||
// build our application with a single route
|
|
||||||
let app = Router::new()
|
|
||||||
.route("/", get(root))
|
|
||||||
.route("/blog", get(blog))
|
|
||||||
.route("/resume", get(resume))
|
|
||||||
.route("/projects", get(projects))
|
|
||||||
.nest_service("/assets", ServeDir::new(format!("{}/assets", assets_path.to_str().unwrap())),);
|
|
||||||
// run our app with hyper, listening globally on port 3000
|
|
||||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
|
||||||
axum::serve(listener, app).await.unwrap();
|
|
||||||
}
|
|
||||||
async fn root() -> impl IntoResponse {
|
|
||||||
let template = HelloTemplate {};
|
|
||||||
HtmlTemplate(template)
|
|
||||||
}
|
|
||||||
async fn blog() -> impl IntoResponse {
|
|
||||||
let template = BlogTemplate {};
|
|
||||||
HtmlTemplate(template)
|
|
||||||
}
|
|
||||||
async fn resume() -> impl IntoResponse {
|
|
||||||
let template = ResumeTemplate {};
|
|
||||||
HtmlTemplate(template)
|
|
||||||
}
|
|
||||||
async fn projects() -> impl IntoResponse {
|
|
||||||
let template = ProjectsTemplate {};
|
|
||||||
HtmlTemplate(template)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Template)]
|
|
||||||
#[template(path = "index.html")]
|
|
||||||
struct HelloTemplate;
|
|
||||||
|
|
||||||
#[derive(Template)]
|
|
||||||
#[template(path = "blog.html")]
|
|
||||||
struct BlogTemplate;
|
|
||||||
|
|
||||||
#[derive(Template)]
|
|
||||||
#[template(path = "resume.html")]
|
|
||||||
struct ResumeTemplate;
|
|
||||||
|
|
||||||
#[derive(Template)]
|
|
||||||
#[template(path = "projects.html")]
|
|
||||||
struct ProjectsTemplate;
|
|
||||||
|
|
||||||
/// A wrapper type that we'll use to encapsulate HTML parsed by askama into valid HTML for axum to serve.
|
|
||||||
struct HtmlTemplate<T>(T);
|
|
||||||
|
|
||||||
/// Allows us to convert Askama HTML templates into valid HTML for axum to serve in the response.
|
|
||||||
impl<T> IntoResponse for HtmlTemplate<T>
|
|
||||||
where
|
|
||||||
T: Template,
|
|
||||||
{
|
|
||||||
fn into_response(self) -> Response {
|
|
||||||
// Attempt to render the template with askama
|
|
||||||
match self.0.render() {
|
|
||||||
// If we're able to successfully parse and aggregate the template, serve it
|
|
||||||
Ok(html) => Html(html).into_response(),
|
|
||||||
// If we're not, return an error or some bit of fallback HTML
|
|
||||||
Err(err) => (
|
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
format!("Failed to render template. Error: {}", err),
|
|
||||||
)
|
|
||||||
.into_response(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
14
src/router.rs
Normal file
14
src/router.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
use axum::{Router, routing::get};
|
||||||
|
use tower_http::services::ServeDir;
|
||||||
|
use std::path::Path;
|
||||||
|
use super::handlers;
|
||||||
|
|
||||||
|
pub fn router(assets_path: &Path) -> Router {
|
||||||
|
Router::new()
|
||||||
|
.route("/", get(handlers::root))
|
||||||
|
.route("/blog", get(handlers::blog))
|
||||||
|
.route("/blog/post", get(handlers::blog_post))
|
||||||
|
.route("/resume", get(handlers::resume))
|
||||||
|
.route("/projects", get(handlers::projects))
|
||||||
|
.nest_service("/assets", ServeDir::new(assets_path))
|
||||||
|
}
|
||||||
52
src/templates.rs
Normal file
52
src/templates.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
use askama::Template;
|
||||||
|
use axum::{
|
||||||
|
http::StatusCode,
|
||||||
|
response::{IntoResponse, Html, Response}
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "post.html")]
|
||||||
|
pub struct PostTemplate {
|
||||||
|
pub title: String,
|
||||||
|
pub description: String,
|
||||||
|
pub post_date: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "index.html")]
|
||||||
|
pub struct HomeTemplate;
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "blog.html")]
|
||||||
|
pub struct BlogTemplate;
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "resume.html")]
|
||||||
|
pub struct ResumeTemplate;
|
||||||
|
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(path = "projects.html")]
|
||||||
|
pub struct ProjectsTemplate;
|
||||||
|
|
||||||
|
/// A wrapper type that we'll use to encapsulate HTML parsed by askama into valid HTML for axum to serve.
|
||||||
|
pub struct HtmlTemplate<T>(pub T);
|
||||||
|
|
||||||
|
/// Allows us to convert Askama HTML templates into valid HTML for axum to serve in the response.
|
||||||
|
impl<T> IntoResponse for HtmlTemplate<T>
|
||||||
|
where
|
||||||
|
T: Template,
|
||||||
|
{
|
||||||
|
fn into_response(self) -> Response {
|
||||||
|
// Attempt to render the template with askama
|
||||||
|
match self.0.render() {
|
||||||
|
// If we're able to successfully parse and aggregate the template, serve it
|
||||||
|
Ok(html) => Html(html).into_response(),
|
||||||
|
// If we're not, return an error or some bit of fallback HTML
|
||||||
|
Err(err) => (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
format!("Failed to render template. Error: {}", err),
|
||||||
|
)
|
||||||
|
.into_response(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="bg-stone-400">
|
<body class="bg-stone-400">
|
||||||
<nav class="bg-stone-800">
|
<nav class="bg-stone-900">
|
||||||
<div class="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
|
<div class="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
|
||||||
<div class="relative flex h-16 items-center justify-between">
|
<div class="relative flex h-16 items-center justify-between">
|
||||||
<div class="absolute inset-y-0 left-0 flex items-center sm:hidden">
|
<div class="absolute inset-y-0 left-0 flex items-center sm:hidden">
|
||||||
|
|
@ -41,14 +41,14 @@
|
||||||
<div class="hidden sm:ml-6 sm:block">
|
<div class="hidden sm:ml-6 sm:block">
|
||||||
<div class="flex space-x-4">
|
<div class="flex space-x-4">
|
||||||
<!-- Current: "bg-gray-900 text-white", Default: "text-gray-300 hover:bg-gray-700 hover:text-white" -->
|
<!-- Current: "bg-gray-900 text-white", Default: "text-gray-300 hover:bg-gray-700 hover:text-white" -->
|
||||||
<a href="/" class="bg-stone-900 text-stone-100 rounded-md px-3 py-2 text-sm font-medium"
|
<a href="/" class="bg-stone-900 text-stone-100 rounded-md px-3 py-2 text-sm font-bold"
|
||||||
aria-current="page">Home</a>
|
aria-current="page">Home</a>
|
||||||
<a href="/blog"
|
<a href="/blog"
|
||||||
class="text-stone-300 hover:bg-stone-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium">Blog</a>
|
class="text-stone-300 hover:bg-stone-700 hover:text-white rounded-md px-3 py-2 text-sm font-bold">Blog</a>
|
||||||
<a href="/projects"
|
<a href="/projects"
|
||||||
class="text-stone-300 hover:bg-stone-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium">Projects</a>
|
class="text-stone-300 hover:bg-stone-700 hover:text-white rounded-md px-3 py-2 text-sm font-bold">Projects</a>
|
||||||
<a href="/resume"
|
<a href="/resume"
|
||||||
class="text-stone-300 hover:bg-stone-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium">Resume</a>
|
class="text-stone-300 hover:bg-stone-700 hover:text-white rounded-md px-3 py-2 text-sm font-bold">Resume</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -62,11 +62,11 @@
|
||||||
<a href="/" class="bg-stone-900 text-white block rounded-md px-3 py-2 text-base font-medium"
|
<a href="/" class="bg-stone-900 text-white block rounded-md px-3 py-2 text-base font-medium"
|
||||||
aria-current="page">Home</a>
|
aria-current="page">Home</a>
|
||||||
<a href="/blog"
|
<a href="/blog"
|
||||||
class="text-stone-300 hover:bg-stone-700 hover:text-white block rounded-md px-3 py-2 text-base font-medium">Blog</a>
|
class="text-stone-300 hover:bg-stone-700 hover:text-white block rounded-md px-3 py-2 text-base font-bold">Blog</a>
|
||||||
<a href="/projects"
|
<a href="/projects"
|
||||||
class="text-stone-300 hover:bg-stone-700 hover:text-white block rounded-md px-3 py-2 text-base font-medium">Projects</a>
|
class="text-stone-300 hover:bg-stone-700 hover:text-white block rounded-md px-3 py-2 text-base font-bold">Projects</a>
|
||||||
<a href="/resume"
|
<a href="/resume"
|
||||||
class="text-stone-300 hover:bg-stone-700 hover:text-white block rounded-md px-3 py-2 text-base font-medium">Resume</a>
|
class="text-stone-300 hover:bg-stone-700 hover:text-white block rounded-md px-3 py-2 text-base font-bold">Resume</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,48 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>HI</h1>
|
<div class="grid grid-cols-3 gap-4 mt-4 mx-4">
|
||||||
|
<div class="cols-span-1 bg-stone-200 pt-12 hover:bg-stone-300">
|
||||||
|
<a href="#"></a>
|
||||||
|
<h1 class="font-extrabold text-center text-2xl">Title</h1>
|
||||||
|
<p class="text-center ml-4">post desc</p>
|
||||||
|
<p class="text-right pt-12 pb-4 mr-12 font-bold">post date</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="cols-span-1 bg-stone-200 pt-12 hover:bg-stone-300">
|
||||||
|
<a href="#">
|
||||||
|
<h1 class="font-extrabold text-center text-2xl">Title</h1>
|
||||||
|
<p class="text-center ml-4">post desc</p>
|
||||||
|
<p class="text-right pt-12 pb-4 mr-12 font-bold">post date</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="cols-span-1 bg-stone-200 pt-12 hover:bg-stone-300">
|
||||||
|
<a href="#">
|
||||||
|
<h1 class="font-extrabold text-center text-2xl">Title</h1>
|
||||||
|
<p class="text-center ml-4">post desc</p>
|
||||||
|
<p class="text-right pt-12 pb-4 mr-12 font-bold">post date</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="cols-span-1 bg-stone-200 pt-12 hover:bg-stone-300">
|
||||||
|
<a href="#">
|
||||||
|
<h1 class="font-extrabold text-center text-2xl">Title</h1>
|
||||||
|
<p class="text-center ml-4">post desc</p>
|
||||||
|
<p class="text-right pt-12 pb-4 mr-12 font-bold">post date</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="cols-span-1 bg-stone-200 pt-12 hover:bg-stone-300">
|
||||||
|
<a href="#">
|
||||||
|
<h1 class="font-extrabold text-center text-2xl">Title</h1>
|
||||||
|
<p class="text-center ml-4">post desc</p>
|
||||||
|
<p class="text-right pt-12 pb-4 mr-12 font-bold">post date</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="cols-span-1 bg-stone-200 pt-12 hover:bg-stone-300">
|
||||||
|
<a href="#">
|
||||||
|
<h1 class="font-extrabold text-center text-2xl">Title</h1>
|
||||||
|
<p class="text-center ml-4">post desc</p>
|
||||||
|
<p class="text-right pt-12 pb-4 mr-12 font-bold">post date</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
@ -24,4 +24,5 @@
|
||||||
social media because I view those as channels primarily for discoverability. In contrast, this website represents my
|
social media because I view those as channels primarily for discoverability. In contrast, this website represents my
|
||||||
own space on the web—a space I own, moderate, and host. This independence ensures that my content remains unaffected
|
own space on the web—a space I own, moderate, and host. This independence ensures that my content remains unaffected
|
||||||
by the profit-driven algorithms of other platforms.</p>
|
by the profit-driven algorithms of other platforms.</p>
|
||||||
{% endblock %}
|
</div>
|
||||||
|
{% endblock %}
|
||||||
8
templates/post.html
Normal file
8
templates/post.html
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1 class="text-4xl">{{ title }}</h1>
|
||||||
|
<p class="font-bold">{{ description }}</p>
|
||||||
|
<p class="font-extrabold">{{ post_date }}</p>
|
||||||
|
{% endblock %}
|
||||||
|
|
@ -2,4 +2,108 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<div class="mx-72">
|
||||||
|
<h1 class="text-4xl mt-12">Things I’ve made trying to put my dent in the universe.</h1>
|
||||||
|
|
||||||
|
<p class="mb-24">I’ve worked on tons of little projects over the years but these are the ones that I’m most proud
|
||||||
|
of.
|
||||||
|
Many of them
|
||||||
|
are open-source, so if you see something that piques your interest, check out the code and contribute if you have
|
||||||
|
ideas
|
||||||
|
for how it can be improved.</p>
|
||||||
|
<ul role="list" class="grid grid-cols-1 gap-x-12 gap-y-16 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
|
<li class="group relative flex flex-col items-start">
|
||||||
|
<div
|
||||||
|
class="relative z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white shadow-md shadow-zinc-800/5 ring-1 ring-zinc-900/5 dark:border dark:border-zinc-700/50 dark:bg-zinc-800 dark:ring-0">
|
||||||
|
<img alt="" loading="lazy" width="32" height="32" decoding="async" data-nimg="1" class="h-8 w-8"
|
||||||
|
style="color: transparent;" src="/assets/sk-extract.png">
|
||||||
|
</div>
|
||||||
|
<h2 class="mt-6 text-base font-semibold text-zinc-800 dark:text-zinc-100">
|
||||||
|
<div
|
||||||
|
class="absolute -inset-x-4 -inset-y-6 z-0 scale-95 bg-zinc-50 opacity-0 transition group-hover:scale-100 group-hover:opacity-100 sm:-inset-x-6 sm:rounded-2xl dark:bg-zinc-800/50">
|
||||||
|
</div><a href="#"><span class="absolute -inset-x-4 -inset-y-6 z-20 sm:-inset-x-6 sm:rounded-2xl"></span><span
|
||||||
|
class="relative z-10">SK-Extract</span></a>
|
||||||
|
</h2>
|
||||||
|
<p class="relative z-10 mt-2 text-sm text-stone-100 dark:text-stone-100">Single binary tool for all of your
|
||||||
|
extraction needs!</p>
|
||||||
|
<p
|
||||||
|
class="relative z-10 mt-6 flex text-sm font-medium text-emerald-300 transition group-hover:text-emerald-500 dark:text-emerald-700">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true" class="h-6 w-6 flex-none">
|
||||||
|
<path
|
||||||
|
d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z"
|
||||||
|
fill="currentColor"></path>
|
||||||
|
</svg><span class="ml-2">github.com</span>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li class="group relative flex flex-col items-start">
|
||||||
|
<div
|
||||||
|
class="relative z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white shadow-md shadow-zinc-800/5 ring-1 ring-zinc-900/5 dark:border dark:border-zinc-700/50 dark:bg-zinc-800 dark:ring-0">
|
||||||
|
<img alt="" loading="lazy" width="32" height="32" decoding="async" data-nimg="1" class="h-8 w-8"
|
||||||
|
style="color: transparent;" src="/assets/SK-test-logo.png">
|
||||||
|
</div>
|
||||||
|
<h2 class="mt-6 text-base font-semibold text-zinc-800 dark:text-zinc-100">
|
||||||
|
<div
|
||||||
|
class="absolute -inset-x-4 -inset-y-6 z-0 scale-95 bg-zinc-50 opacity-0 transition group-hover:scale-100 group-hover:opacity-100 sm:-inset-x-6 sm:rounded-2xl dark:bg-zinc-800/50">
|
||||||
|
</div><a href="#"><span class="absolute -inset-x-4 -inset-y-6 z-20 sm:-inset-x-6 sm:rounded-2xl"></span><span
|
||||||
|
class="relative z-10">Skout-Bot</span></a>
|
||||||
|
</h2>
|
||||||
|
<p class="relative z-10 mt-2 text-sm text-stone-100 dark:text-stone-100">A discord bot to help manage my private
|
||||||
|
server.</p>
|
||||||
|
<p
|
||||||
|
class="relative z-10 mt-6 flex text-sm font-medium text-emerald-300 transition group-hover:text-emerald-500 dark:text-emerald-700">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true" class="h-6 w-6 flex-none">
|
||||||
|
<path
|
||||||
|
d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z"
|
||||||
|
fill="currentColor"></path>
|
||||||
|
</svg><span class="ml-2">github.com</span>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li class="group relative flex flex-col items-start">
|
||||||
|
<div
|
||||||
|
class="relative z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white shadow-md shadow-zinc-800/5 ring-1 ring-zinc-900/5 dark:border dark:border-zinc-700/50 dark:bg-zinc-800 dark:ring-0">
|
||||||
|
<img alt="" loading="lazy" width="32" height="32" decoding="async" data-nimg="1" class="h-8 w-8"
|
||||||
|
style="color: transparent;" src="/assets/sunserver.png">
|
||||||
|
</div>
|
||||||
|
<h2 class="mt-6 text-base font-semibold text-zinc-800 dark:text-zinc-100">
|
||||||
|
<div
|
||||||
|
class="absolute -inset-x-4 -inset-y-6 z-0 scale-95 bg-zinc-50 opacity-0 transition group-hover:scale-100 group-hover:opacity-100 sm:-inset-x-6 sm:rounded-2xl dark:bg-zinc-800/50">
|
||||||
|
</div><a href="#"><span class="absolute -inset-x-4 -inset-y-6 z-20 sm:-inset-x-6 sm:rounded-2xl"></span><span
|
||||||
|
class="relative z-10">Sun Server</span></a>
|
||||||
|
</h2>
|
||||||
|
<p class="relative z-10 mt-2 text-sm text-stone-100 dark:text-stone-100">Data source for Node RED lighting control
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
class="relative z-10 mt-6 flex text-sm font-medium text-emerald-300 transition group-hover:text-emerald-500 dark:text-emerald-700">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true" class="h-6 w-6 flex-none">
|
||||||
|
<path
|
||||||
|
d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z"
|
||||||
|
fill="currentColor"></path>
|
||||||
|
</svg><span class="ml-2">github.com</span>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
<li class="group relative flex flex-col items-start">
|
||||||
|
<div
|
||||||
|
class="relative z-10 flex h-12 w-12 items-center justify-center rounded-full bg-white shadow-md shadow-zinc-800/5 ring-1 ring-zinc-900/5 dark:border dark:border-zinc-700/50 dark:bg-zinc-800 dark:ring-0">
|
||||||
|
<img alt="" loading="lazy" width="32" height="32" decoding="async" data-nimg="1" class="h-8 w-8"
|
||||||
|
style="color: transparent;" src="/assets/aocollapse.png">
|
||||||
|
</div>
|
||||||
|
<h2 class="mt-6 text-base font-semibold text-zinc-800 dark:text-zinc-100">
|
||||||
|
<div
|
||||||
|
class="absolute -inset-x-4 -inset-y-6 z-0 scale-95 bg-zinc-50 opacity-0 transition group-hover:scale-100 group-hover:opacity-100 sm:-inset-x-6 sm:rounded-2xl dark:bg-zinc-800/50">
|
||||||
|
</div><a href="#"><span class="absolute -inset-x-4 -inset-y-6 z-20 sm:-inset-x-6 sm:rounded-2xl"></span><span
|
||||||
|
class="relative z-10">AO Collapse</span></a>
|
||||||
|
</h2>
|
||||||
|
<p class="relative z-10 mt-2 text-sm text-stone-100 dark:text-stone-100">Wave Function Collapse proceduaral
|
||||||
|
generation library written in rust.</p>
|
||||||
|
<p
|
||||||
|
class="relative z-10 mt-6 flex text-sm font-medium text-emerald-300 transition group-hover:text-emerald-500 dark:text-emerald-700">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true" class="h-6 w-6 flex-none">
|
||||||
|
<path
|
||||||
|
d="M15.712 11.823a.75.75 0 1 0 1.06 1.06l-1.06-1.06Zm-4.95 1.768a.75.75 0 0 0 1.06-1.06l-1.06 1.06Zm-2.475-1.414a.75.75 0 1 0-1.06-1.06l1.06 1.06Zm4.95-1.768a.75.75 0 1 0-1.06 1.06l1.06-1.06Zm3.359.53-.884.884 1.06 1.06.885-.883-1.061-1.06Zm-4.95-2.12 1.414-1.415L12 6.344l-1.415 1.413 1.061 1.061Zm0 3.535a2.5 2.5 0 0 1 0-3.536l-1.06-1.06a4 4 0 0 0 0 5.656l1.06-1.06Zm4.95-4.95a2.5 2.5 0 0 1 0 3.535L17.656 12a4 4 0 0 0 0-5.657l-1.06 1.06Zm1.06-1.06a4 4 0 0 0-5.656 0l1.06 1.06a2.5 2.5 0 0 1 3.536 0l1.06-1.06Zm-7.07 7.07.176.177 1.06-1.06-.176-.177-1.06 1.06Zm-3.183-.353.884-.884-1.06-1.06-.884.883 1.06 1.06Zm4.95 2.121-1.414 1.414 1.06 1.06 1.415-1.413-1.06-1.061Zm0-3.536a2.5 2.5 0 0 1 0 3.536l1.06 1.06a4 4 0 0 0 0-5.656l-1.06 1.06Zm-4.95 4.95a2.5 2.5 0 0 1 0-3.535L6.344 12a4 4 0 0 0 0 5.656l1.06-1.06Zm-1.06 1.06a4 4 0 0 0 5.657 0l-1.061-1.06a2.5 2.5 0 0 1-3.535 0l-1.061 1.06Zm7.07-7.07-.176-.177-1.06 1.06.176.178 1.06-1.061Z"
|
||||||
|
fill="currentColor"></path>
|
||||||
|
</svg><span class="ml-2">github.com</span>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
@ -2,5 +2,4 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>HI</h1>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue