diff --git a/assets/images/books/alchemised.png b/assets/images/books/alchemised.png new file mode 100644 index 0000000..06b0b99 Binary files /dev/null and b/assets/images/books/alchemised.png differ diff --git a/assets/images/books/designing-data.svg b/assets/images/books/designing-data.svg new file mode 100644 index 0000000..af6deda --- /dev/null +++ b/assets/images/books/designing-data.svg @@ -0,0 +1,6 @@ + + + + Designing Data-Intensive Apps + + diff --git a/assets/images/books/phoenix-project.svg b/assets/images/books/phoenix-project.svg new file mode 100644 index 0000000..66d5f2b --- /dev/null +++ b/assets/images/books/phoenix-project.svg @@ -0,0 +1,6 @@ + + + + The Phoenix Project + + diff --git a/assets/images/books/rust-book.svg b/assets/images/books/rust-book.svg new file mode 100644 index 0000000..cfbe3ec --- /dev/null +++ b/assets/images/books/rust-book.svg @@ -0,0 +1,6 @@ + + + + The Rust Programming Language + + diff --git a/assets/images/dvds/akira.svg b/assets/images/dvds/akira.svg new file mode 100644 index 0000000..b1e5324 --- /dev/null +++ b/assets/images/dvds/akira.svg @@ -0,0 +1,12 @@ + + + + + + + + + + AKIRA + + diff --git a/assets/images/dvds/assassination_classroom.jpg b/assets/images/dvds/assassination_classroom.jpg new file mode 100644 index 0000000..7a4ae5d Binary files /dev/null and b/assets/images/dvds/assassination_classroom.jpg differ diff --git a/assets/images/dvds/blade-runner.svg b/assets/images/dvds/blade-runner.svg new file mode 100644 index 0000000..97b3206 --- /dev/null +++ b/assets/images/dvds/blade-runner.svg @@ -0,0 +1,15 @@ + + + + + + + + + + BLADE + + + RUNNER + + diff --git a/assets/images/dvds/dandadan.png b/assets/images/dvds/dandadan.png new file mode 100644 index 0000000..c9b8747 Binary files /dev/null and b/assets/images/dvds/dandadan.png differ diff --git a/assets/images/dvds/ghost-in-shell.svg b/assets/images/dvds/ghost-in-shell.svg new file mode 100644 index 0000000..ab3c8b4 --- /dev/null +++ b/assets/images/dvds/ghost-in-shell.svg @@ -0,0 +1,15 @@ + + + + + + + + + + GHOST IN + + + THE SHELL + + diff --git a/assets/images/dvds/matrix.svg b/assets/images/dvds/matrix.svg new file mode 100644 index 0000000..9ee4dd7 --- /dev/null +++ b/assets/images/dvds/matrix.svg @@ -0,0 +1,9 @@ + + + + THE + + + MATRIX + + diff --git a/assets/sass/pages/now.scss b/assets/sass/pages/now.scss new file mode 100644 index 0000000..303a753 --- /dev/null +++ b/assets/sass/pages/now.scss @@ -0,0 +1,1748 @@ +// Server Room - Horizontal Scrolling Now/Uses Page + +// Color variables +$color-green: #0f0; +$color-amber: #ff9900; +$color-blue: #0ff; +$color-red: #f00; + +$dark-bg-1: #1a1a1a; +$dark-bg-2: #2a2a2a; +$dark-bg-3: #0a0a0a; + +// Mixins for common patterns +@mixin led-color($color) { + background: $color; + color: $color; +} + +@mixin panel-unit { + background: linear-gradient( + 90deg, + $dark-bg-2 0%, + $dark-bg-1 50%, + $dark-bg-2 100% + ); + border: 1px solid #444; + border-radius: 3px; + position: relative; + box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.1); +} + +@mixin monitor-color-variant($color) { + .metrics-header, + .metric-label, + .metric-value, + .graph-legend, + .terminal-output, + .network-label, + .network-value { + color: $color; + text-shadow: 0 0 5px $color; + } + + .metrics-header { + border-bottom-color: $color; + } + + .metric-bar { + border-color: $color; + } + + .metric-fill { + background: linear-gradient(90deg, $color 0%, darken($color, 10%) 100%); + box-shadow: 0 0 10px $color; + } + + .graph-grid { + background-image: + repeating-linear-gradient( + 0deg, + rgba($color, 0.1) 0px, + transparent 1px, + transparent 30px + ), + repeating-linear-gradient( + 90deg, + rgba($color, 0.1) 0px, + transparent 1px, + transparent 30px + ); + } +} + +.server-room { + width: 100vw; + height: 100vh; + background: + repeating-linear-gradient( + 90deg, + $dark-bg-2 0px, + $dark-bg-2 100px, + #252525 100px, + #252525 101px + ), + linear-gradient(180deg, $dark-bg-1 0%, $dark-bg-2 50%, $dark-bg-1 100%); + overflow-x: auto; + overflow-y: hidden; + position: relative; + + @include scrollbar-custom($color-green, 8px); +} + +.server-room-container { + display: flex; + align-items: flex-end; + min-width: max-content; + height: 100%; + padding: 20px; + gap: 60px; + position: relative; +} + +// Ceiling with cable trays +.server-room::before { + content: ""; + position: sticky; + left: 0; + top: 0; + width: 100%; + height: 80px; + background: + repeating-linear-gradient( + 90deg, + $dark-bg-3 0px, + $dark-bg-3 200px, + $dark-bg-1 200px, + $dark-bg-1 205px + ), + linear-gradient(180deg, #000 0%, $dark-bg-1 100%); + border-bottom: 2px solid #333; + z-index: 100; + pointer-events: none; +} + +// Floor grid +.server-room::after { + content: ""; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 30%; + background: + repeating-linear-gradient( + 90deg, + transparent 0px, + transparent 99px, + rgba(255, 255, 255, 0.03) 99px, + rgba(255, 255, 255, 0.03) 100px + ), + repeating-linear-gradient( + 0deg, + transparent 0px, + transparent 99px, + rgba(255, 255, 255, 0.03) 99px, + rgba(255, 255, 255, 0.03) 100px + ); + pointer-events: none; + z-index: 1; +} + +// Server Rack +.server-rack { + position: relative; + width: 250px; + background: linear-gradient( + 180deg, + $dark-bg-1 0%, + $dark-bg-3 50%, + $dark-bg-1 100% + ); + border: 3px solid #333; + border-radius: 8px; + box-shadow: + 0 10px 40px rgba(0, 0, 0, 0.8), + inset 0 0 20px rgba(0, 0, 0, 0.5); + z-index: 10; +} + +.rack-frame { + padding: 15px 10px; + display: flex; + flex-direction: column; + gap: 8px; +} + +.rack-label { + background: #000; + color: $color-green; + font-family: monospace; + font-size: 12px; + padding: 5px; + text-align: center; + border: 1px solid $color-green; + margin-bottom: 10px; + text-shadow: 0 0 5px $color-green; +} + +.server-unit { + height: 45px; + @include panel-unit; +} + +.server-front-panel { + display: flex; + align-items: center; + padding: 0 10px; + height: 100%; + gap: 8px; +} + +// LED base styling +.server-led, +.switch-status-led, +.ups-led, +.storage-drive-led { + border-radius: 50%; + box-shadow: 0 0 8px currentColor; + animation: pulse 2s ease-in-out infinite; +} + +.server-led { + width: 6px; + height: 6px; +} + +.switch-status-led { + width: 5px; + height: 5px; +} + +.ups-led { + width: 8px; + height: 8px; + animation-duration: 2.5s; +} + +.storage-drive-led { + width: 4px; + height: 4px; +} + +// LED color variants - shared across all LED types +@each $name, + $color + in ( + green: $color-green, + amber: $color-amber, + blue: $color-blue, + red: $color-red + ) +{ + .led-#{$name} { + @include led-color($color); + } +} + +// Server LED animation staggering +@for $i from 1 through 8 { + .server-unit:nth-child(#{$i}) .server-led { + animation-delay: #{($i - 1) * 0.2}s; + } + + .server-unit:nth-child(#{$i}) .server-led:nth-child(2) { + animation-delay: #{($i - 1) * 0.2 + 0.5}s; + } +} + +.server-drive-bays { + display: flex; + gap: 4px; + margin-left: auto; +} + +.drive-bay { + width: 30px; + height: 20px; + background: #000; + border: 1px solid #333; + border-radius: 2px; +} + +.server-vents { + width: 60px; + height: 25px; + background: repeating-linear-gradient( + 90deg, + $dark-bg-3 0px, + $dark-bg-3 2px, + transparent 2px, + transparent 4px + ); + margin-left: 10px; +} + +.rack-legs { + position: absolute; + bottom: -20px; + left: 10%; + right: 10%; + height: 20px; + background: linear-gradient(180deg, #333 0%, $dark-bg-1 100%); + border-radius: 0 0 5px 5px; +} + +// Server unit sizing +@for $i from 1 through 4 { + .server-#{$i}u { + height: #{45 * $i + ($i - 1) * 5}px; + } +} + +// Common labels +.server-label, +.switch-label, +.patch-label, +.ups-label, +.storage-label { + font-family: monospace; + font-size: 9px; + color: #999; + padding: 2px 5px; + white-space: nowrap; +} + +// Network Switch +.network-switch { + height: 45px; + background: linear-gradient( + 90deg, + $dark-bg-1 0%, + $dark-bg-3 50%, + $dark-bg-1 100% + ); + border: 1px solid #333; + border-radius: 3px; + position: relative; + box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.05); +} + +.switch-front-panel { + display: flex; + align-items: center; + height: 100%; + gap: 10px; + position: relative; +} + +.switch-ports { + display: grid; + grid-template-columns: repeat(12, 1fr); + gap: 2px; + flex: 1; + padding: 5px; +} + +.switch-port { + width: 8px; + height: 12px; + background: #000; + border: 1px solid #222; + border-radius: 1px; + position: relative; + + &.active::before { + content: ""; + position: absolute; + top: 2px; + left: 50%; + transform: translateX(-50%); + width: 3px; + height: 3px; + background: $color-green; + border-radius: 50%; + box-shadow: 0 0 4px $color-green; + animation: blink-fast 1.5s infinite; + } + + // Randomized delays for active ports + $delays: + 0.73s, 0.21s, 0.94s, 0.11s, 0.58s, 1.22s, 0.37s, 0.85s, 0.04s, 0.67s, 1.15s, + 0.42s, 0.98s, 0.29s, 0.76s, 0.13s, 1.08s, 0.51s, 0.89s, 0.33s, 1.01s, 0.46s, + 0.19s, 0.62s; + + @each $delay in $delays { + $i: index($delays, $delay); + &.active:nth-child(#{$i})::before { + animation-delay: $delay; + } + } +} + +.switch-leds { + display: flex; + flex-direction: column; + gap: 3px; + padding-right: 10px; +} + +.switch-status-led { + @for $i from 1 through 3 { + &:nth-child(#{$i}) { + animation-delay: #{($i - 1) * 0.4}s; + } + } +} + +@keyframes blink-fast { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.2; + } +} + +// Patch Panel +.patch-panel { + height: 45px; + @include panel-unit; +} + +.patch-front { + display: flex; + align-items: center; + padding: 0 10px; + height: 100%; + gap: 10px; +} + +.patch-ports { + display: grid; + grid-template-columns: repeat(12, 1fr); + gap: 3px; + flex: 1; + padding: 5px; +} + +.patch-port { + width: 10px; + height: 15px; + background: #000; + border: 1px solid #333; + border-radius: 2px; + position: relative; + + &.connected::after { + content: ""; + position: absolute; + bottom: -3px; + left: 50%; + transform: translateX(-50%); + width: 6px; + height: 8px; + background: $color-amber; + border-radius: 1px; + box-shadow: 0 0 3px $color-amber; + } +} + +// UPS Unit +.ups-unit { + height: 90px; + background: linear-gradient(90deg, #3a3a3a 0%, $dark-bg-2 50%, #3a3a3a 100%); + border: 1px solid #444; + border-radius: 3px; + position: relative; + box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.1); +} + +.ups-front-panel { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 15px; + height: 100%; + gap: 10px; +} + +.ups-display { + flex: 1; + display: flex; + justify-content: center; +} + +.ups-lcd { + background: #1a3a1a; + color: $color-green; + font-family: "DSEG7-Classic", monospace; + font-size: 16px; + padding: 8px 15px; + border: 2px solid $dark-bg-3; + border-radius: 3px; + text-shadow: 0 0 8px $color-green; + box-shadow: inset 0 0 10px rgba(0, 255, 0, 0.2); +} + +.ups-indicators { + display: flex; + flex-direction: column; + gap: 8px; +} + +.ups-led { + @for $i from 1 through 2 { + &:nth-child(#{$i}) { + animation-delay: #{($i - 1) * 0.6}s; + } + } +} + +// Storage Unit +.storage-unit { + height: 145px; + @include panel-unit; +} + +.storage-front-panel { + padding: 10px; + height: 100%; + display: flex; + flex-direction: column; + gap: 5px; +} + +.storage-drive-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 5px; + flex: 1; +} + +.storage-drive { + background: $dark-bg-3; + border: 1px solid #333; + border-radius: 2px; + display: flex; + align-items: center; + justify-content: center; + position: relative; + + &::before { + content: ""; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 80%; + height: 2px; + background: $dark-bg-1; + } +} + +// Storage drive LED animation staggering +@for $i from 1 through 12 { + .storage-drive-grid .storage-drive:nth-child(#{$i}) .storage-drive-led { + animation-delay: #{($i - 1) * 0.15}s; + } +} + +// Blank Panel +.blank-panel { + height: 45px; + background: linear-gradient( + 90deg, + $dark-bg-1 0%, + $dark-bg-3 50%, + $dark-bg-1 100% + ); + border: 1px solid #333; + border-radius: 3px; + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5); +} + +// Rack Spacer +.rack-spacer { + height: 10px; +} + +// Monitor Screen +.monitor-screen { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + z-index: 10; +} + +.monitor-bezel { + border-radius: 8px; + padding: 15px 20px 30px 20px; + box-shadow: + 0 15px 35px rgba(0, 0, 0, 0.7), + inset 0 2px 4px rgba(255, 255, 255, 0.2), + inset 0 -2px 4px rgba(0, 0, 0, 0.3); + position: relative; + + &.monitor-bezel-green { + background: linear-gradient(145deg, #c8c8c0, #a8a898); + } + + &.monitor-bezel-amber { + background: linear-gradient(145deg, #d8d0b8, #b8b098); + } + + &.monitor-bezel-blue { + background: linear-gradient(145deg, #b8b8b0, #989888); + } +} + +.monitor-display { + width: 100%; + height: 100%; + background: #000; + border-radius: 5px; + position: relative; + overflow: hidden; + box-shadow: inset 0 0 40px rgba(0, 255, 100, 0.1); + + &.monitor-display-green { + @include monitor-color-variant($color-green); + box-shadow: inset 0 0 40px rgba(0, 255, 100, 0.1); + } + + &.monitor-display-amber { + @include monitor-color-variant($color-amber); + box-shadow: inset 0 0 40px rgba(255, 153, 0, 0.1); + } + + &.monitor-display-blue { + @include monitor-color-variant($color-blue); + box-shadow: inset 0 0 40px rgba(0, 255, 255, 0.1); + } +} + +.monitor-content { + padding: 15px; + height: 100%; + position: relative; + z-index: 1; +} + +.monitor-scanlines { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: repeating-linear-gradient( + 0deg, + rgba(0, 0, 0, 0.15) 0px, + rgba(0, 0, 0, 0.15) 1px, + transparent 1px, + transparent 2px + ); + pointer-events: none; + z-index: 2; + animation: scanline 8s linear infinite; +} + +.monitor-power-led { + position: absolute; + bottom: 8px; + right: 20px; + width: 6px; + height: 6px; + border-radius: 50%; + box-shadow: 0 0 8px currentColor; + animation: pulse 2s ease-in-out infinite; + + &.monitor-led-green { + @include led-color($color-green); + } + &.monitor-led-amber { + @include led-color($color-amber); + } + &.monitor-led-blue { + @include led-color($color-blue); + } +} + +.monitor-stand { + width: 60px; + height: 40px; + background: linear-gradient(180deg, #888 0%, #666 100%); + border-radius: 0 0 8px 8px; + margin-top: -5px; + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + + &::before { + content: ""; + position: absolute; + bottom: -8px; + left: 50%; + transform: translateX(-50%); + width: 80px; + height: 12px; + background: linear-gradient(90deg, transparent, #555, transparent); + border-radius: 50%; + opacity: 0.6; + } +} + +// Metrics Display +.metrics-header { + font-family: monospace; + font-size: 14px; + margin-bottom: 15px; + padding-bottom: 5px; + border-bottom: 1px solid currentColor; +} + +.metrics-grid { + display: flex; + flex-direction: column; + gap: 15px; +} + +.metric-item { + display: grid; + grid-template-columns: 60px 1fr 50px; + gap: 10px; + align-items: center; +} + +.metric-label { + font-family: monospace; + font-size: 12px; +} + +.metric-bar { + height: 18px; + background: $dark-bg-3; + border: 1px solid currentColor; + border-radius: 2px; + overflow: hidden; + position: relative; +} + +.metric-fill { + height: 100%; + position: relative; + + &::after { + content: ""; + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 30%; + background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3)); + } +} + +.metric-fill-animated { + animation: metric-pulse 3s ease-in-out infinite; +} + +@keyframes metric-pulse { + 0%, + 100% { + opacity: 0.8; + } + 50% { + opacity: 1; + } +} + +.metric-value { + font-family: "DSEG7-Classic", monospace; + font-size: 14px; + text-align: right; +} + +// Graph Display +.graph-container { + height: 200px; + position: relative; + margin: 20px 0; + overflow: hidden; +} + +.graph-wrapper { + position: absolute; + inset: 0; + display: flex; + width: 200%; + animation: graph-scroll 15s linear infinite; +} + +.graph-instance { + width: 50%; + height: 100%; + flex-shrink: 0; +} + +@keyframes graph-scroll { + 0% { + transform: translateX(0); + } + 100% { + transform: translateX(-50%); + } +} + +.graph-grid { + position: absolute; + inset: 0; + pointer-events: none; + z-index: 1; +} + +.graph-svg { + position: relative; + width: 100%; + height: 100%; +} + +.graph-line { + stroke-width: 2; + + &.graph-line-green { + stroke: $color-green; + filter: drop-shadow(0 0 3px $color-green); + } + &.graph-line-amber { + stroke: $color-amber; + filter: drop-shadow(0 0 3px $color-amber); + } + &.graph-line-blue { + stroke: $color-blue; + filter: drop-shadow(0 0 3px $color-blue); + } +} + +.graph-fill { + opacity: 0.2; + + &.graph-fill-green { + fill: $color-green; + } + &.graph-fill-amber { + fill: $color-amber; + } + &.graph-fill-blue { + fill: $color-blue; + } +} + +.graph-legend { + font-family: monospace; + font-size: 11px; + margin-top: 10px; +} + +// Terminal Output +.terminal-output { + font-family: monospace; + font-size: 12px; + line-height: 1.6; +} + +.terminal-line { + margin: 5px 0; +} + +.status-active { + color: $color-green; + font-weight: bold; +} + +.terminal-cursor { + margin-top: 15px; +} + +// Log Display +.log-container { + font-family: monospace; + font-size: 11px; + line-height: 1.8; + max-height: 250px; + overflow: hidden; + position: relative; +} + +.log-line { + color: $color-green; + text-shadow: 0 0 3px $color-green; + animation: log-scroll 15s linear infinite; + opacity: 0; + + @for $i from 1 through 10 { + &:nth-child(#{$i}) { + animation-delay: #{$i * 0.5}s; + } + } + + &.log-warning { + color: $color-amber; + text-shadow: 0 0 3px $color-amber; + } + + &.log-error { + color: $color-red; + text-shadow: 0 0 3px $color-red; + } + + &.log-success { + color: $color-green; + text-shadow: 0 0 3px $color-green; + font-weight: bold; + } +} + +@keyframes log-scroll { + 0% { + transform: translateY(0); + opacity: 0; + } + 10% { + opacity: 1; + } + 90% { + opacity: 1; + } + 100% { + transform: translateY(-20px); + opacity: 0; + } +} + +// Network Traffic +.network-stats { + display: flex; + flex-direction: column; + gap: 30px; + margin-top: 20px; +} + +.network-row { + display: grid; + grid-template-columns: 50px 1fr 80px; + gap: 15px; + align-items: center; +} + +.network-label { + font-family: monospace; + font-size: 14px; + font-weight: bold; +} + +.network-graph { + display: flex; + gap: 3px; + align-items: flex-end; + height: 60px; +} + +.network-bar { + flex: 1; + border-radius: 2px 2px 0 0; + animation: network-bar-pulse 2s ease-in-out infinite; + + @for $i from 1 through 20 { + &:nth-child(#{$i}) { + height: random(80) + 20%; + animation-delay: #{$i * 0.1}s; + } + } + + &.network-bar-rx { + background: $color-green; + box-shadow: 0 0 5px $color-green; + } + + &.network-bar-tx { + background: $color-blue; + box-shadow: 0 0 5px $color-blue; + } +} + +.monitor-display-amber { + .network-bar.network-bar-rx { + background: $color-amber; + box-shadow: 0 0 5px $color-amber; + } + + .network-bar.network-bar-tx { + background: #ffcc00; + box-shadow: 0 0 5px #ffcc00; + } +} + +@keyframes network-bar-pulse { + 0%, + 100% { + opacity: 0.7; + transform: scaleY(1); + } + 50% { + opacity: 1; + transform: scaleY(1.1); + } +} + +.network-value { + font-family: "DSEG7-Classic", monospace; + font-size: 12px; + text-align: right; +} + +// Whiteboard +.whiteboard { + position: relative; + background: #f5f5f5; + border: 8px solid #8b7355; + border-radius: 8px; + box-shadow: + 0 10px 40px rgba(0, 0, 0, 0.6), + inset 0 0 100px rgba(200, 200, 200, 0.3); + z-index: 10; +} + +.whiteboard-surface { + width: 100%; + height: 100%; + padding: 20px; + position: relative; + background: + radial-gradient( + circle at 20% 30%, + rgba(150, 150, 150, 0.1) 0%, + transparent 50% + ), + radial-gradient( + circle at 80% 70%, + rgba(150, 150, 150, 0.08) 0%, + transparent 50% + ), + repeating-linear-gradient( + 0deg, + transparent 0px, + transparent 24px, + rgba(200, 200, 200, 0.15) 24px, + rgba(200, 200, 200, 0.15) 25px + ), + repeating-linear-gradient( + 90deg, + transparent 0px, + transparent 24px, + rgba(200, 200, 200, 0.15) 24px, + rgba(200, 200, 200, 0.15) 25px + ), + #fafafa; + background-position: + 0 0, + 0 0, + 20px 20px, + 20px 20px, + 0 0; +} + +.whiteboard-title { + font-family: "Caveat", cursive; + font-size: 28px; + font-weight: bold; + color: $dark-bg-1; + margin-bottom: 15px; + padding-bottom: 8px; + position: relative; + display: inline-block; + + &::after { + content: ""; + position: absolute; + bottom: 0; + left: -5px; + right: -5px; + width: 120%; + height: 15px; + background: linear-gradient( + 90deg, + transparent 0%, + #333 2%, + #333 98%, + transparent 100% + ); + clip-path: polygon( + 0% 60%, + 3% 45%, + 8% 55%, + 15% 40%, + 22% 50%, + 28% 35%, + 35% 48%, + 42% 52%, + 48% 45%, + 55% 55%, + 62% 48%, + 68% 52%, + 75% 45%, + 82% 50%, + 88% 40%, + 93% 52%, + 97% 48%, + 100% 55%, + 100% 65%, + 97% 58%, + 93% 62%, + 88% 50%, + 82% 60%, + 75% 55%, + 68% 62%, + 62% 58%, + 55% 65%, + 48% 55%, + 42% 62%, + 35% 58%, + 28% 45%, + 22% 60%, + 15% 50%, + 8% 65%, + 3% 55%, + 0% 70% + ); + opacity: 0.95; + } +} + +.whiteboard-content { + font-family: "Caveat", cursive; + font-size: 20px; + color: $dark-bg-1; + line-height: 1.8; + + p { + margin: 10px 0; + } + + ul, + ol { + margin-left: 20px; + } + + ul li { + list-style: none; + position: relative; + font-size: 1.4rem; + line-height: 1.6rem; + margin-bottom: 1rem; + + &::before { + content: "●"; + position: absolute; + left: -20px; + top: -0.2em; + font-size: 10px; + line-height: 1.8rem; + transform: rotate(20deg) scale(1.2, 0.9); + opacity: 0.85; + text-shadow: + 1px 0 0 currentColor, + -1px 1px 0 currentColor, + 0 -1px 0 currentColor; + } + + // Vary the scribbled dots slightly + &:nth-child(2n)::before { + transform: rotate(-15deg) scale(0.95, 1.1); + } + + &:nth-child(3n)::before { + transform: rotate(35deg) scale(1.1, 0.85); + } + + &:nth-child(5n)::before { + transform: rotate(-25deg) scale(1.05, 0.95); + opacity: 0.9; + } + } + + a { + background: linear-gradient(120deg, #d946ef 0%, #0ea5e9 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + text-decoration: none; + position: relative; + font-weight: 600; + display: inline; + + &::after { + content: ""; + position: absolute; + bottom: 2px; + left: 0; + right: 0; + height: 2px; + background: linear-gradient(120deg, #d946ef 0%, #0ea5e9 100%); + clip-path: polygon( + 0% 55%, + 5% 40%, + 12% 50%, + 20% 35%, + 28% 48%, + 38% 42%, + 48% 52%, + 58% 38%, + 68% 50%, + 78% 42%, + 88% 48%, + 95% 40%, + 100% 52%, + 100% 62%, + 95% 50%, + 88% 58%, + 78% 52%, + 68% 60%, + 58% 48%, + 48% 62%, + 38% 52%, + 28% 58%, + 20% 45%, + 12% 60%, + 5% 50%, + 0% 65% + ); + opacity: 1; + } + + // External link icon + &[target="_blank"]::before { + content: "🌐"; + font-size: 0.6em; + margin-right: 3px; + display: inline-block; + } + + &:hover { + &::after { + opacity: 1; + } + } + } +} + +// Whiteboard Notes +.wb-notes { + position: absolute; + top: 10px; + right: 20px; + display: flex; + flex-direction: row-reverse; + gap: 15px; + z-index: 5; +} + +.wb-note { + width: 100px; + min-height: 90px; + padding: 10px; + font-family: "Caveat", cursive; + font-size: 14px; + line-height: 1.4; + position: relative; + flex-shrink: 0; + box-shadow: + 2px 2px 8px rgba(0, 0, 0, 0.15), + 0 0 0 1px rgba(0, 0, 0, 0.05); + transition: transform 0.2s ease; + + &:nth-child(1) { + transform: rotate(1deg); + } + + &:nth-child(2) { + transform: rotate(-2deg); + } + + &:nth-child(3) { + transform: rotate(2deg); + } + + // Pin at the top + &::before { + content: ""; + position: absolute; + top: -4px; + left: 50%; + transform: translateX(-50%); + width: 8px; + height: 8px; + background: radial-gradient(circle, #666 0%, #333 60%); + border-radius: 50%; + box-shadow: + 0 1px 2px rgba(0, 0, 0, 0.3), + inset 0 1px 1px rgba(255, 255, 255, 0.3); + } +} + +.wb-note-content { + word-wrap: break-word; +} + +// Whiteboard note colors +.wb-note-yellow { + background: linear-gradient(135deg, #fff59d 0%, #ffeb3b 100%); +} + +.wb-note-pink { + background: linear-gradient(135deg, #f8bbd0 0%, #f48fb1 100%); +} + +.wb-note-blue { + background: linear-gradient(135deg, #bbdefb 0%, #90caf9 100%); +} + +.wb-note-green { + background: linear-gradient(135deg, #c5e1a5 0%, #aed581 100%); +} + +.wb-note-orange { + background: linear-gradient(135deg, #ffcc80 0%, #ffb74d 100%); +} + +.wb-note-purple { + background: linear-gradient(135deg, #ce93d8 0%, #ba68c8 100%); +} + +// Bookshelf +.bookshelf { + width: 400px; + height: 500px; + position: relative; + background: linear-gradient(90deg, #4a3528 0%, #3a2518 50%, #4a3528 100%); + border-radius: 5px; + box-shadow: 0 10px 40px rgba(0, 0, 0, 0.7); + z-index: 10; + display: flex; + flex-direction: column; + justify-content: flex-start; + padding: 10px; + padding-bottom: 30px; +} + +.bookshelf-title { + font-family: monospace; + font-size: 11px; + color: #d4a574; + text-align: center; + padding: 5px; + background: rgba(0, 0, 0, 0.3); + border-radius: 3px; + margin-bottom: 5px; + text-transform: uppercase; + letter-spacing: 1px; +} + +.shelf { + position: relative; + width: 100%; + height: 23%; + margin: 5px 0; +} + +.shelf-board { + position: absolute; + bottom: 0; + width: 100%; + height: 15px; + background: linear-gradient(180deg, #6a4a3a 0%, #4a3528 100%); + border-radius: 2px; + box-shadow: + 0 -2px 5px rgba(0, 0, 0, 0.3), + inset 0 -1px 2px rgba(0, 0, 0, 0.4); +} + +.shelf-items { + position: absolute; + top: 0; + left: 10px; + right: 10px; + height: calc(100% - 15px); + display: flex; + gap: 3px; + align-items: flex-start; +} + +.shelf-books { + @extend .shelf-items; +} + +.shelf-item { + position: relative; + transition: transform 0.2s ease; + overflow: hidden; + + &:hover { + transform: translateY(-5px); + } + + &.item { + width: 45px !important; + height: 65px; + background: #000; + border: 1px solid #333; + border-radius: 2px; + box-shadow: + 0 2px 6px rgba(0, 0, 0, 0.5), + inset 0 0 3px rgba(255, 255, 255, 0.1); + + img.dvd-cover { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + border-radius: 1px; + } + } + + &.current { + transform: translateY(-8px); + z-index: 5; + + &::before { + content: ""; + position: absolute; + inset: -3px; + background: linear-gradient(180deg, #ffd700 0%, #ff8c00 100%); + border-radius: 3px; + z-index: -1; + animation: current-pulse 2s ease-in-out infinite; + } + + .current-indicator { + position: absolute; + top: -20px; + left: 50%; + transform: translateX(-50%); + white-space: nowrap; + z-index: 10; + } + + .current-glow { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 120%; + height: 120%; + background: radial-gradient( + circle, + rgba(255, 215, 0, 0.3) 0%, + transparent 70% + ); + animation: glow-pulse 2s ease-in-out infinite; + } + + .current-label { + font-family: monospace; + font-size: 8px; + font-weight: bold; + color: #ffd700; + background: rgba(0, 0, 0, 0.8); + padding: 2px 6px; + border-radius: 3px; + text-shadow: 0 0 5px #ffd700; + border: 1px solid #ffd700; + position: relative; + z-index: 11; + } + } +} + +@keyframes current-pulse { + 0%, + 100% { + opacity: 0.8; + box-shadow: 0 0 10px rgba(255, 215, 0, 0.5); + } + 50% { + opacity: 1; + box-shadow: 0 0 20px rgba(255, 215, 0, 0.8); + } +} + +@keyframes glow-pulse { + 0%, + 100% { + opacity: 0.5; + transform: translate(-50%, -50%) scale(1); + } + 50% { + opacity: 0.8; + transform: translate(-50%, -50%) scale(1.1); + } +} + +.bookshelf-frame { + position: absolute; + inset: -5px; + border: 5px solid #2a1a0f; + border-radius: 5px; + pointer-events: none; + z-index: 1; +} + +.bookshelf-legs { + position: absolute; + bottom: -40px; + left: 0; + right: 0; + height: 40px; + display: flex; + justify-content: space-between; + padding: 0 30px; + pointer-events: none; + z-index: 0; +} + +.bookshelf-leg { + width: 50px; + height: 100%; + background: linear-gradient(180deg, #5a4a38 0%, #3a2a18 100%); + border: 2px solid #2a1a0f; + border-top: none; + box-shadow: + 0 5px 15px rgba(0, 0, 0, 0.6), + inset 0 2px 4px rgba(255, 255, 255, 0.05); + position: relative; + + &::after { + content: ""; + position: absolute; + bottom: -8px; + left: -8px; + right: -8px; + height: 8px; + background: linear-gradient(180deg, #3a2a18 0%, #2a1a0f 100%); + border-radius: 0 0 4px 4px; + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.8); + } + + &.leg-left { + border-radius: 0 0 0 3px; + } + + &.leg-right { + border-radius: 0 0 3px 0; + } +} + +// Computer terminal on desk +.terminal-desk { + width: 400px; + height: 500px; + position: relative; + z-index: 10; +} + +.desk-surface { + position: absolute; + bottom: 0; + width: 100%; + height: 100px; + background: linear-gradient(180deg, #2d1f12 0%, #1d1208 100%); + box-shadow: 0 -5px 20px rgba(0, 0, 0, 0.7); + + &::before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 3px; + background: linear-gradient(90deg, #1d1208, #0d0804, #1d1208); + } +} + +.terminal-monitor { + position: absolute; + bottom: 100px; + left: 50%; + transform: translateX(-50%); + width: 350px; + height: 280px; + background: linear-gradient(145deg, #e8e0c8, #c4b89a); + border-radius: 8px; + padding: 15px 20px 30px 20px; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.8); +} + +.terminal-screen { + width: 100%; + height: 100%; + background: #000; + border-radius: 5px; + padding: 10px; + font-family: monospace; + font-size: 12px; + color: $color-green; + overflow-y: auto; + box-shadow: inset 0 0 40px rgba(0, 255, 100, 0.1); + + @include scrollbar-custom($color-green, 3px); +} + +// Ambient lighting effects +.ambient-light { + position: absolute; + border-radius: 50%; + filter: blur(40px); + opacity: 0.3; + pointer-events: none; + animation: ambient-pulse 4s ease-in-out infinite; + + &.green { + background: $color-green; + } + &.blue { + background: #00f; + } + &.amber { + background: $color-amber; + } +} + +@keyframes ambient-pulse { + 0%, + 100% { + opacity: 0.2; + transform: scale(1); + } + 50% { + opacity: 0.4; + transform: scale(1.1); + } +} + +// Server room sign/title +.server-room-sign { + position: fixed; + top: 100px; + left: 50%; + transform: translateX(-50%); + z-index: 150; + pointer-events: none; +} + +.sign-frame { + background: linear-gradient(145deg, $dark-bg-2 0%, $dark-bg-1 100%); + border: 8px solid #444; + border-radius: 8px; + padding: 20px 40px; + box-shadow: + 0 10px 30px rgba(0, 0, 0, 0.8), + inset 0 2px 4px rgba(255, 255, 255, 0.1); + position: relative; + + &::before { + content: ""; + position: absolute; + top: -4px; + left: -4px; + right: -4px; + bottom: -4px; + background: linear-gradient(145deg, #555 0%, #333 100%); + border-radius: 12px; + z-index: -1; + } +} + +.sign-content { + text-align: center; +} + +.sign-title { + font-family: "Courier New", monospace; + font-size: 48px; + font-weight: bold; + color: $color-green; + text-shadow: + 0 0 10px $color-green, + 0 0 20px $color-green, + 0 0 30px $color-green; + letter-spacing: 8px; + margin-bottom: 5px; + animation: sign-flicker 4s infinite; +} + +.sign-subtitle { + font-family: "Courier New", monospace; + font-size: 12px; + color: #888; + letter-spacing: 3px; + text-transform: uppercase; +} + +@keyframes sign-flicker { + 0%, + 100% { + opacity: 1; + } + 2%, + 4% { + opacity: 0.8; + } + 6% { + opacity: 1; + } + 94% { + opacity: 1; + } + 96% { + opacity: 0.9; + } +} + +// Shared animations +@keyframes pulse { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } +} + +@keyframes scanline { + 0% { + transform: translateY(0); + } + 100% { + transform: translateY(10px); + } +} + +// Responsive adjustments +@include media-down(lg) { + .server-room-container { + gap: 40px; + } + + .server-rack { + width: 200px; + } + + .whiteboard { + min-width: 300px; + } + + .bookshelf { + min-width: 250px; + } +} diff --git a/assets/sass/style.scss b/assets/sass/style.scss index eae3b3d..8bddcf5 100644 --- a/assets/sass/style.scss +++ b/assets/sass/style.scss @@ -17,6 +17,7 @@ @import "pages/about"; @import "pages/audio"; +@import "pages/now"; @import url("https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&family=Neonderthaw&display=swap"); diff --git a/content/media/neon-odin-allfather/index.md b/content/media/neon-odin-allfather/index.md index f69f5e0..667a5ef 100644 --- a/content/media/neon-odin-allfather/index.md +++ b/content/media/neon-odin-allfather/index.md @@ -4,6 +4,9 @@ date: 2025-01-12 tags: ["album"] description: "" cover: "cover.jpg" +render: never +build: + render: never --- Neon Odin's _Allfather_ feels like mythology filtered through analog circuits and a CRT glow (much like myself). The album merges darksynth with handcrafted Nordic folk instruments - talharpa and nyckelharpa built by the artist himself - creating something that shouldn't work but absolutely does. diff --git a/content/media/ninajirachi-i-love-my-computer/index.md b/content/media/ninajirachi-i-love-my-computer/index.md index 98ae273..87dbe74 100644 --- a/content/media/ninajirachi-i-love-my-computer/index.md +++ b/content/media/ninajirachi-i-love-my-computer/index.md @@ -4,13 +4,15 @@ date: 2025-12-12 tags: ["album"] description: "" cover: "cover.jpg" +build: + render: never --- Ninajirachi's _I Love My Computer_ captures something truthful about growing up shaped by screens and bandwidth. The album explores that strange intimacy we developed with our machines - the late nights, the secret discoveries, the way technology became less of a tool and more of a companion. Tracks like "Fuck My Computer" and "iPod Touch" aren't just bangers; they're confessions about a relationship that transcends generations. Whether you learned HTML on Geocities or taught yourself production in GarageBand, there's recognition here. -The production has a restless energy, shifting between euphoric and introspective, mirroring how the internet itself feels—chaotic, isolating, and strangely beautiful all at once. It's a debut album that understands what it meant to have your world widened by a glowing rectangle - and I relate deeply to its content despite being at least one generation older than Ninajirachi. +The production has a restless energy, shifting between euphoric and introspective, mirroring how the internet itself feels - chaotic, isolating, and strangely beautiful all at once. It's a debut album that understands what it meant to have your world widened by a glowing rectangle - and I relate deeply to its content despite being at least one generation older than Ninajirachi. Not my usual genre of listen, but it has been a regular spin since it came into my world. diff --git a/content/now/currently.md b/content/now/currently.md new file mode 100644 index 0000000..d6e2653 --- /dev/null +++ b/content/now/currently.md @@ -0,0 +1,15 @@ +--- +title: Currently +width: 500px +height: 550px +sticky_notes: + - text: "Remember to update blog!" + color: "yellow" + - text: "New feature idea: dark mode toggle" + color: "pink" +--- + +**Tinkering with:** + +- ritual.sh - This website! I've been exploring the indieweb movement and working on this site to carve out my own little digital garden to tend. I'm having a lot of fun making art using pure CSS. +- After years of using Linux exclusively for servers, Microsoft's relentless [enshittification](https://en.wikipedia.org/wiki/Enshittification) of Windows finally pushed me to migrate my actual workstations. Now running Linux on most machines (currently experimenting with Bazzite) and MacOS on the rest. Desktop customisation is as enjoyable as it was back in the day - maybe more so. diff --git a/content/now/daily-drivers.md b/content/now/daily-drivers.md new file mode 100644 index 0000000..ae37568 --- /dev/null +++ b/content/now/daily-drivers.md @@ -0,0 +1,23 @@ +--- +title: Daily Drivers +width: 450px +height: 550px +order: 3 +--- + +**Desktop:** + +- OS: Bazzite Linux +- DE: KDE Plasma +- Terminal: kitty +- Editor: VSCode / Neovim +- Browser: Firefox +- Shell: Zsh + Oh My Zsh + +**Hardware:** + +- CPU: Ryzen 7 9800X3D +- GPU: Radeon RX 7900 XTX +- RAM: 64GB DDR5 +- Camera: Fuji X-T5 +- Audio: Hiby R4 EVA, Fiio FT-1 diff --git a/content/now/homelab.md b/content/now/homelab.md new file mode 100644 index 0000000..340a416 --- /dev/null +++ b/content/now/homelab.md @@ -0,0 +1,28 @@ +--- +title: Homelab Architecture +width: 550px +height: 600px +order: 4 +--- + +**Network Topology:** + +``` +Internet + | + +-- Firewall + | + +-- Core Switch + | + +-- PROD Servers + +-- DEV Environment + +-- Storage/NAS + +-- Services +``` + +**Self-Hosted Services:** + +- Git server, CI/CD +- Media server +- Home automation +- Monitoring stack diff --git a/content/now.md b/content/now/index.md similarity index 100% rename from content/now.md rename to content/now/index.md diff --git a/content/now/learning-queue.md b/content/now/learning-queue.md new file mode 100644 index 0000000..c9daf08 --- /dev/null +++ b/content/now/learning-queue.md @@ -0,0 +1,21 @@ +--- +title: Learning Queue +width: 400px +height: 500px +order: 2 +--- + +**2025 Goals:** + +- Master Rust programming +- Build a complete homelab +- Contribute to FOSS projects +- Advanced photography +- Music production basics +- Kubernetes certification + +**Books in Progress:** + +- The Rust Programming Language +- Designing Data-Intensive Applications +- The Phoenix Project diff --git a/content/updates/2025-12-08-homepage.md b/content/updates/2025-12-08-homepage.md index 6be34c4..fdc508b 100644 --- a/content/updates/2025-12-08-homepage.md +++ b/content/updates/2025-12-08-homepage.md @@ -3,6 +3,8 @@ title: "2025 12 08 Homepage" date: 2025-12-08T14:02:19Z tags: [] description: "" +build: + render: never --- First version of the homepage created with the interactive terminal. diff --git a/content/updates/2025-12-09-about.md b/content/updates/2025-12-09-about.md index 599471f..9735fff 100644 --- a/content/updates/2025-12-09-about.md +++ b/content/updates/2025-12-09-about.md @@ -3,6 +3,8 @@ title: "2025 12 09 About" date: 2025-12-09T14:07:59Z tags: [] description: "" +build: + render: never --- Added initial version of the about page with some approximation of a manifesto. diff --git a/content/updates/2025-12-13-album-reviews.md b/content/updates/2025-12-13-album-reviews.md index 8074411..f8d3cf7 100644 --- a/content/updates/2025-12-13-album-reviews.md +++ b/content/updates/2025-12-13-album-reviews.md @@ -3,6 +3,8 @@ title: "2025 12 13 Album Reviews" date: 2025-12-13T15:16:18Z tags: [] description: "" +build: + render: never --- Added some of my thoughts about Allfather by Neon Odin and I Love My Computer by Ninajirachi diff --git a/content/updates/2025-12-13-music.md b/content/updates/2025-12-13-music.md index 17c4ee1..0297c19 100644 --- a/content/updates/2025-12-13-music.md +++ b/content/updates/2025-12-13-music.md @@ -3,6 +3,8 @@ title: "2025 12 13 Music" date: 2025-12-13T14:09:08Z tags: [] description: "" +build: + render: never --- Created the music and audio gear section! diff --git a/layouts/now/single.html b/layouts/now/single.html index fa84737..59d9de0 100644 --- a/layouts/now/single.html +++ b/layouts/now/single.html @@ -1,37 +1,176 @@ - - - - - - Basement Window - - - -
Coming soon...
- - + + {{ partial "elements/whiteboard.html" (dict "file" "currently.md" "context" .) }} + + + + {{ partial "elements/server-rack.html" + (dict "height" "650px" "title" "STORAGE-01" + "units" (slice + (dict "type" "server" "label" "NAS-01" "led1" "green" "led2" "green" "drives" 1 "size" 1) + (dict "type" "spacer") + (dict "type" "storage" "label" "SAN-Primary" "drives" 12 "size" 3) + (dict "type" "spacer") + (dict "type" "server" "label" "Backup-01" "led1" "blue" "led2" "amber" "drives" 2) + (dict "type" "blank") + ) ) }} + + +
+
+
+
+

$ whoami

+

dan@ritual.sh

+
+

$ cat current_stack.txt

+

Languages: JavaScript, TypeScript, Python, Rust (learning)

+

Frontend: React, Vue, Hugo

+

Backend: Node.js, FastAPI

+

DevOps: Docker, Linux, Git

+

Interests: Homelab, Self-hosting, Open Source

+
+

$ uptime

+

+ {{ now.Format "15:04:05" }} up 42 days, load average: 0.15, 0.23, + 0.18 +

+
+

_

+
+
+
+
+
+
+ + + + {{ partial "elements/bookshelf.html" (dict + "width" "350px" + "height" "600px" + "title" "Currently Reading" + "type" "books" + "shelves" 1 + "items" (slice + (dict "image" "images/books/alchemised.png" "title" "Alchemised" "current" true) + ) + ) }} + + + {{ partial "elements/whiteboard.html" (dict "file" "daily-drivers.md" "context" .) }} + + + + {{ partial "elements/server-rack.html" + (dict "height" "700px" "title" "DEV-RACK-01" + "units" (slice + (dict "type" "switch" "label" "Dev-SW-01" "ports" 24) + (dict "type" "patch-panel" "label" "Patch-Dev" "ports" 24) + (dict "type" "spacer") + (dict "type" "server" "label" "Dev-01" "led1" "green" "led2" "amber" "drives" 2) + (dict "type" "server" "label" "Dev-02" "led1" "blue" "led2" "green" "drives" 2) + (dict "type" "server" "label" "Test-01" "led1" "green" "led2" "red" "drives" 1) + (dict "type" "spacer") + (dict "type" "server" "label" "CI/CD" "led1" "green" "led2" "green" "drives" 2) + (dict "type" "blank") + (dict "type" "server" "label" "Monitoring" "led1" "blue" "led2" "amber" "drives" 1) + )) }} + + + {{ partial "elements/whiteboard.html" (dict "file" "learning-queue.md" "context" .) }} + + + + {{ partial "elements/server-rack.html" (dict "height" "550px" "title" + "INFRA-01" "units" (slice (dict "type" "ups" "label" "UPS-Primary" + "capacity" "98" "size" 2) (dict "type" "spacer") (dict "type" "switch" + "label" "Edge-SW-01" "ports" 24) (dict "type" "server" "label" "Firewall" + "led1" "green" "led2" "green" "drives" 1) (dict "type" "server" "label" + "DNS/DHCP" "led1" "green" "led2" "blue" "drives" 1) (dict "type" "blank") + (dict "type" "blank") ) ) }} + + + + {{ partial "elements/bookshelf.html" (dict "width" "400px" "height" "550px" + "title" "DVD Collection" "type" "dvds" "shelves" 2 "items" (slice (dict + "image" "images/dvds/dandadan.png" "title" "DAN DA DAN" "current" true) + (dict "image" "images/dvds/assassination_classroom.jpg" "title" + "Assassination Classroom") ) ) }} + + + {{ partial "elements/whiteboard.html" (dict "file" "homelab.md" "context" .) }} + + + {{ partial "elements/monitor-screen.html" (dict "width" "400px" "height" + "350px" "type" "metrics" "title" "WEB-01 - METRICS" "color" "green" ) }} + + + {{ partial "elements/monitor-screen.html" (dict "width" "450px" "height" + "380px" "type" "graph" "title" "NETWORK TRAFFIC" "color" "blue" ) }} + + + {{ partial "elements/monitor-screen.html" (dict "width" "420px" "height" + "400px" "type" "logs" "title" "SYSTEM LOGS" "color" "green" ) }} + + + {{ partial "elements/monitor-screen.html" (dict "width" "380px" "height" + "380px" "type" "network" "title" "BANDWIDTH MONITOR" "color" "amber" ) }} + + + {{ partial "elements/monitor-screen.html" (dict "width" "400px" "height" + "320px" "type" "terminal" "title" "db-primary.local" "color" "green" ) }} + + + + +{{ end }} diff --git a/layouts/partials/elements/bookshelf.html b/layouts/partials/elements/bookshelf.html new file mode 100644 index 0000000..3a67634 --- /dev/null +++ b/layouts/partials/elements/bookshelf.html @@ -0,0 +1,39 @@ +{{ $items := .items | default (slice) }} {{ $shelves := .shelves | default 4 }} +{{ $width := .width | default "300px" }} {{ $height := .height | default "400px" +}} {{ $type := .type | default "books" }} {{ $title := .title | default "" }} + +
+ {{ if $title }} +
{{ $title }}
+ {{ end }} {{ range seq $shelves }} +
+
+
+ {{ if $items }} {{ range $items }} +
+ {{ if .image }} {{ $img := resources.Get .image }} {{ if $img }} {{ + $resized := $img.Resize "100x120" }} + {{ .title }} + {{ end }} {{ end }} {{ if .current }} +
+
+
+ {{ if eq $type "dvds" }}WATCHING{{ else }}READING{{ end }} +
+
+ {{ end }} +
+ {{ end }} {{ end }} +
+
+ {{ end }} +
+
+
+
+
+
diff --git a/layouts/partials/elements/monitor-screen.html b/layouts/partials/elements/monitor-screen.html new file mode 100644 index 0000000..139b737 --- /dev/null +++ b/layouts/partials/elements/monitor-screen.html @@ -0,0 +1,142 @@ +{{ $width := .width | default "400px" }} +{{ $height := .height | default "350px" }} +{{ $type := .type | default "metrics" }} +{{ $title := .title | default "System Monitor" }} +{{ $color := .color | default "green" }} + +
+
+
+
+ + {{ if eq $type "metrics" }} + +
{{ $title }}
+
+
+
CPU
+
+
+
+
67%
+
+
+
RAM
+
+
+
+
82%
+
+
+
DISK
+
+
+
+
45%
+
+
+
NET
+
+
+
+
34%
+
+
+ + {{ else if eq $type "graph" }} + +
{{ $title }}
+
+
+ + + + + + + + + + +
+
+
+
+ ▲ Throughput: 2.4 GB/s +
+ + {{ else if eq $type "terminal" }} + +
+
$ systemctl status
+
● {{ $title }}
+
Loaded: loaded (/etc/systemd/system/)
+
Active: active (running)
+
Memory: 2.4G
+
CPU: 12.5%
+
$_
+
+ + {{ else if eq $type "logs" }} + +
{{ $title }}
+
+
[OK] Started Network Manager
+
[OK] Started User Login Management
+
[WARN] High memory usage detected
+
[INFO] Service nginx.service reloaded
+
[OK] Mounted /mnt/storage
+
[OK] System backup completed
+
[INFO] Connection established
+
[OK] Started Docker Engine
+
[ERR] Failed to resolve hostname
+
[INFO] Firewall rules updated
+
+ + {{ else if eq $type "network" }} + +
{{ $title }}
+
+
+
↓ RX
+
+ {{ range seq 20 }} +
+ {{ end }} +
+
24.3 MB/s
+
+
+
↑ TX
+
+ {{ range seq 20 }} +
+ {{ end }} +
+
12.8 MB/s
+
+
+ + {{ end }} + +
+ + +
+
+ + +
+
+ + +
+
diff --git a/layouts/partials/elements/server-rack.html b/layouts/partials/elements/server-rack.html new file mode 100644 index 0000000..67d4b71 --- /dev/null +++ b/layouts/partials/elements/server-rack.html @@ -0,0 +1,116 @@ +{{ $height := .height | default "600px" }} +{{ $title := .title | default "" }} +{{ $units := .units | default (slice) }} + +
+
+ {{ if $title }} +
{{ $title }}
+ {{ end }} + + {{ if $units }} + {{ range $units }} + {{ if eq .type "server" }} +
+
+
+
+ {{ if .label }} +
{{ .label }}
+ {{ end }} +
+ {{ range seq (.drives | default 2) }} +
+ {{ end }} +
+
+
+
+ {{ else if eq .type "switch" }} +
+
+ {{ if .label }} +
{{ .label }}
+ {{ end }} +
+ {{ range seq (.ports | default 24) }} +
+ {{ end }} +
+
+
+
+
+
+
+
+ {{ else if eq .type "patch-panel" }} +
+
+ {{ if .label }} +
{{ .label }}
+ {{ end }} +
+ {{ range seq (.ports | default 24) }} +
+ {{ end }} +
+
+
+ {{ else if eq .type "ups" }} +
+
+ {{ if .label }} +
{{ .label }}
+ {{ end }} +
+
+ {{ .capacity | default "100" }}% +
+
+
+
+
+
+
+
+ {{ else if eq .type "storage" }} +
+
+ {{ if .label }} +
{{ .label }}
+ {{ end }} +
+ {{ range seq (.drives | default 12) }} +
+
+
+ {{ end }} +
+
+
+ {{ else if eq .type "blank" }} +
+ {{ else if eq .type "spacer" }} +
+ {{ end }} + {{ end }} + {{ else }} + + {{ range seq 8 }} +
+
+
+
+
+
+
+
+
+
+
+ {{ end }} + {{ end }} +
+
+
diff --git a/layouts/partials/elements/whiteboard.html b/layouts/partials/elements/whiteboard.html new file mode 100644 index 0000000..678f383 --- /dev/null +++ b/layouts/partials/elements/whiteboard.html @@ -0,0 +1,23 @@ +{{ $file := .file }} +{{ $context := .context }} +{{ with $context.Resources.GetMatch $file }} +
+
+
{{ .Title }}
+
+ {{ .Content }} +
+ {{ if .Params.sticky_notes }} +
+ {{ range $index, $note := .Params.sticky_notes }} + {{ if lt $index 3 }} +
+
{{ $note.text }}
+
+ {{ end }} + {{ end }} +
+ {{ end }} +
+
+{{ end }}