favicons added
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
@@ -0,0 +1,93 @@
|
|||||||
|
%PDF-1.4
|
||||||
|
%“Œ‹ž ReportLab Generated PDF document (opensource)
|
||||||
|
1 0 obj
|
||||||
|
<<
|
||||||
|
/F1 2 0 R /F2 3 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
2 0 obj
|
||||||
|
<<
|
||||||
|
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
3 0 obj
|
||||||
|
<<
|
||||||
|
/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
4 0 obj
|
||||||
|
<<
|
||||||
|
/Contents 9 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
|
||||||
|
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||||
|
>> /Rotate 0 /Trans <<
|
||||||
|
|
||||||
|
>>
|
||||||
|
/Type /Page
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
5 0 obj
|
||||||
|
<<
|
||||||
|
/Contents 10 0 R /MediaBox [ 0 0 612 792 ] /Parent 8 0 R /Resources <<
|
||||||
|
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||||
|
>> /Rotate 0 /Trans <<
|
||||||
|
|
||||||
|
>>
|
||||||
|
/Type /Page
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
6 0 obj
|
||||||
|
<<
|
||||||
|
/PageMode /UseNone /Pages 8 0 R /Type /Catalog
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
7 0 obj
|
||||||
|
<<
|
||||||
|
/Author (\(anonymous\)) /CreationDate (D:20260502182436+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260502182436+00'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||||
|
/Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
8 0 obj
|
||||||
|
<<
|
||||||
|
/Count 2 /Kids [ 4 0 R 5 0 R ] /Type /Pages
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
9 0 obj
|
||||||
|
<<
|
||||||
|
/Filter [ /ASCII85Decode /FlateDecode ] /Length 2874
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
Gb!SmgN)%.&q0LUoM\eYQ"42Il>79h:,K5HN29,5<qunG+UK*Ni..UD:$ou>2ZZfUXG^Abg+#m'YpC#r!/IIJ?YG(G5Bc]]9E79#iV^h&gO]/%Cp3<Dr#.3NB7HH)Au%NTHQES"Ibu7*'YMo(HtsE]h\oYkBE3J8*s;Z^eFG00)1`/Zc9[@Or2;S+IQ=_a><&9^cDm1OSh4ObE"dP_(XKA%$1nq$/=7lU]0=FP[,?I5*RYggL!F5JEXimsP-(O;hS]9K0`Qh8s+WaTj0l.NDqXd(VX9Nmg=qDlpK`FQXnP>:jc1>E#IkN4>_o4)=:DNY?LT4qbB,12c5#-h_]__&Kjo>$b-39+X*8e3.e1-d)<8#a#qL[&p"5=l0]l!i)%686%6LrUm;(:U1\@7''Ma(6+mt`C1%9h2nXr,=SWRRF3Uem#@-B:OIOl&40&4YNW\&>lU]1<L`9B:jf5hq`IWdLmZm,\H5F)ThEBf]0ZZ-9$WdLIDk95mK,hB:FYt2Y$8>OcYOe*@e<n;W*q88->ZtJ=qp=%n;,gWU&n(6@PER/LtKh_PsJ@Xkb('<]H[QPTm,G[[dCJ#*6g@;8%PNV*_qu,YhI.shXO4UIJ%q"7ScP]AK)HS"[.t1K=_=JWq7LUl4KW4XL[B76G]n>fu+3tpOWcZ%2"FS6;+g;!,mkj.m"dUuU"74D)]b0lWca@%`d&m<GF@HD\+)"C_RfgoImA0Wmn-Ktf;u[>Cc;Y9o!W5I-Q/HAtJVE<*3J`YjZGn9(OKc)s0QLE\/g8i4]>2i#,$(pSUr4KRCH+CbbLQJD.@&n,&[+L[JnPgWcu)5Y`JSSZ44N#WF-^nkcZk88&V&4C*1jAGBCT_:r*Jlh10]]>^3YlW,B0305Oqog$*LA=WqY>-krLqa>WdgE'^PV^R?A0MQpcb.O$^sQVWN=%KTl!K?J[j^N\\\U1/2J8aKZhDr6^5EDVf7(0io[9*RF@!`aA1HE-DIJ>4NS&\9F$=%n]5_ZBD?@\HicKr^SE;mH[9/aG?l2+p1XWZN;F&_$s/g:iVf]A;%HY"\juSbq;gT@_.4kbdnA-YU&fE61_lP5#]:`WQY_^RYUedeb;K`T+J#aa'<-25N4l@'D/DTS@@d1-PDX=Gk1[OI_:fnXLTRo%<QQfARhpr?pL"Pn7UWI*9S0YjucnF16tSLo4'ifCpSco=\uc)^B7`3_76qg!I'4;7f/s32oKLA*X[g,B/'%pC/Pnh1+>n\>>ui[*@$R]FcIBJ?>VMYAolQq%\)6rZ7V9PcLKn!NRGFEq35Z8&\FoESVuk-JrQS@K+$2B]d0rSCprNo>Vt).J-,+'qnijq=plfb["\-a5*9R%6i(K7Qo5*])94kh9(M*0%)*%*[8iYc,-GjW5_^,/iCd4-7/U30aPPr"Jr]jlM/_dRfYFM,mVF8CLCnX@f>QYQg_Qt0kDfiRnEmLhf-2e$0Jp$7,6ZeG5*ld.l+GsMrVJ3PaRD8m?+@j-n=p=;CW&2D9=d*>AJm(/L,>E1\Dct,YsI<L;ZV(e;c-'mqhIJD:'K?A`>3^\MCT"RoUs,>oK2Ss_riek)\^Fl0VQ5Z14]m)mlM1(r@OqJp[8V8':]Ds>@(-*49eJu.U9\nO)NDZF0S+t\jMNX=O^=j6/p\Fg&s^S;K4"oE$Z3J@W@@PR4cGWN=IZ45ESpQMRn#=Cn]njV@l4JPI]H@"DKPZ)+o5t'T6F\d*)V_h5]8re'7N42Aok\&O6(6F`q8*W_SkB7WOo;9&]Q6''"UTnkMWNQGO]]au^JAlXE;7quIh:$bru;2@Gek:t._SDm%D61F1I?;&J+M!.f2@if'd+Qq\[\+:KVrkXj"@L_FRP@\mT^66aSFohCKUWL-U:I'K4fO/Jl-_*Xu`,a2>A78mtB;M>.AMD^Uj"0"PA<EZTAQE>CQU7B#T*mDj&?/mnH,,pAs%>7kM'/:nB_:YVX.b''3B>npDf\MBL9_K54:,"_CnSn<MYEsI^bM1/#Oo4#Qg7*dler7+TWpjNA&"HR`%urm,><^tdDbg+cf&X!RS(m\lm6_+JFJ0u`[\fK6"HMg:Ca+lO,5eBTjA0QkP0mXk>lphT'ao.5hf?L7b3f"2h^*76PB:ouY9nSQX1NmD+!itj"p6DrI=r#+M4im2W.qh.!QkGh>?]m!%m*+*a0f8KD?DZq*,'lgAEkIh<3pJCB\_-#rV>\"OGR$Im81F(g)4eo`Q^&SDssaLO*%_+bVH/TG(6OV[nmTG];;q"#'I2tUPY8%OWi2ZWa%F@@?iM<&p>u#1QYd@e(B#bOB/@&VSAEuW&,VS]cdi#Ah#nGNLEcS<NQY'.02`#7912$XgDe]7>L/3NM[^)hEF6'VE)[UF``<?<QpL=[E_uaeU/qoL]iigjA77HAQC`BEFoY>?S#k+dN$"BK+d4sRj[@B34L`SI"fS;BoSo%Kj]R)%\\WGkh>GID_VnO]8UN;[[k,Upb>bHiS,aD=/Lk>X1BZb2k(,;73,q7-HJN)!I0NqVRNXO/6K$QH-#"-$^iJcoCXN-erJ?/3_ck`Y>&>qVX2Pmp-r)H\eps?"HOeOK@Q_&\aBKV:p:Y2;k9qq$K4%20oZ&qUa9nDL753^el`=@-V[4])KI)J6%iSCibra)dKgu''c0u?o;7nRQnaeE8Ubm5fs!Ybo+ErUF*+S;Pa8"B8kV-4=!gnu#WtT7[(;b]HF]5;:p#?:Jk1\g[boe9l;If=`7H5ANrB*ZT5cJOj3u8[Jq<ba/B_K7l@9H9/=()-`@dB++(ChFUtfL,AVNL%dn<LCWu`MN@/E[V&JTl45dkl(%)`)N,H#_!Wa8*UiJLQ5V+sOSV2g^I`L[W&'/:;7N!#%\DS918!o)(;.T&2&08mU56N~>endstream
|
||||||
|
endobj
|
||||||
|
10 0 obj
|
||||||
|
<<
|
||||||
|
/Filter [ /ASCII85Decode /FlateDecode ] /Length 2700
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
Gb!TY>C5)6(5D;L/(R^EAl!An2GC:[8QquO23?MgU,TrT5uZJ-82^eSIP8e[aFUp>nhcgm:BRj*Q9MGDY(Q+lNB`I!*G5@B@lQSn^i<eQK&^'!N6gEm]_BaDZQ/3uQL@3%"]c2o8+;IScH,6Vo3pC$fR<D>qBC.a#Hj,5<WM.g*)DV[4E[?q&#<Sn[aPU)I!#P+LG.JdlNMMRfH4*^+_1oJi0Y9b/2EZ\E0="":9".#`dbo$htkcnnRm8q5O^8N`A_B=QL"3K-NqUKs1n3k^[$$DVs!Bfl","hX7EjuMf>'jm(9]A_\^o6!T,o^`B,#+<YP<,E'g.Yde-X=Y1Dsm]rpaT(&3e&4eC/$1Ta]e<i_hErhq)?bub!V)UEH?`KX6-?'0F7G-m^RrM<_9ZhVd.[@F2P&_Has03Tf\47`PApV/[bA7gSFg-0Cq7aA[rFffs[N8<im':,![T-c7eKU4J;Glj.l"HOu8+pA$H/gc6=asepeOfB,+a@)jITq'B,>_!M%;79%3p,pOTFifX]RH?i0@^T0-n@=jGaQ/XXH2pR5Ac5@7@!O5Y.V0?]Q))3[Wi1MKM@<+W9)M+5r"e[eXn"p:h7'lp)HVcAPu:Qp:=W$oP3#W`86un2N+Rp&.h*k(16I2mW01bkR?4)-#SRB,k%qYAmaC/[5GE-7oN(,Lj##U"g9&S%&pi%"BMS,cf%=Cc,<60f^RW5;Dae.4-V,6Rd7VDkPIR7/[3E_]`![DZ3G3=^O@.@IICcN25=%O0g.BtgnVF5e5YnmN)lNjp76[UW+n;[$AOPQ$#>5?SgmKt+iB1u*3T9CiV-aq,TlPj_$&_H89*gfJO8T+@N62Rh(s<2^4OXD2G_p)Lk]d<Nk*SOV5tias;+8><MR@54D^A*(MdDN"+#/_l$)_bl%9n9E=J?!N:@BRG&p/bm"3W!gE/r<^qW3[b')*B0?m85aB3KI<#^a/oQAnSAc<CXmcr#<Gm/nA]r_p)='EobJ!i7*2"'Nd#nX%1QZa)_M%a^_hSgNXar_q<:<$f9D4KlP:K,X86$dg+hkCD9>3[Mrt,/hE=e5;JV:"qMq]A'=D"g:IVCE5h8I]nru?Or0)"cheZ^u9Sm#EHP%_m3sC-P^7`%(CF*EGO<>4*jQX_!"<:($"C2_]YHq-C<<f@:n@j/!f,:SBb5qaZYji_m)b:pbBl]M4_[HW=9u!ceX#">Y-tHQ9Ii,N,fGE+-^@hU&M1]X>@bf>bD#0*7"#-:Cq)_/e!6^+^D^Lg*%Z@DJ\!<@>BVWFaa)Ka^@5GS'hXaGZd,Dl[`XAo]:'7K!61Xe8rS5\*9`Ck)uWE1KHP?>tOQF`iE,l]I%)l*aZk*rPQ#eN;sc;rF+$+gV)C$cO^imU(Z@((d7[phH!JMY5O6N*mitT$8*q9R["JTBhKE%ml"EGFG2t,3c6V/R&J\+T`=rlSqgF+iQrM,I?TYo5e_NHL#fu(I6!JR,.?JK_6@3V`D"@kMF@a'lX>[0Y9s,76S,s!Zq^M!3\umq:*qRTL9g/0kDqIQJ`u5<Y;;W;QFB20h.X5^N'sF=1O[O]bpM9G1UZAn`Xm4nQE!+3IC4nK]n(XtT;0Sf:*NQ"*&'8`81@Fe@B/6rTp?tUENlOK:?RH04C6N[4N$)RpL*=V8iW(^k`c1uc]*T?(J/BHmY,SPdFuX&fTA#0e9e&em:HX53YbR1=!cR(B0o9.f'$(pSFZE)d]f^RER5%K-Dcfnq1iRY[cis6gK"XZ2pcA('br'#B'm0VRT=)d+!aF_[Xm=Y0[48kUQkn#02S<i`a?,(dqS4En7A6R>0/42LALIFX*36eY+GNZ:"MF<I`-B$+eMH`4OHPI,Z\ssUZ^=>_#OEM.6Zht]<EmGY`>-46>;ohfPdEI)g4&f[HlUZiXTFX<?VQ7%;a(ec[G?uI&\[email protected]#:1nFA5_ca5mB*=Gp:!pC24T:Gm&GOg@qV;oiXTr6Z)>?irY!E)W-oj&;5*2JJmEODXr=f"^Ds3n<UU$s-0'2.m&0Ed#U^A!i03K]jEp:JNmH!3s6_X%*T.W03AY4?]if%"&CrIPGF0?(5qEoDHF70Y;o5N+Wfq$g.H=oa'1T9Sd(U-V4Nff;ESN9UfP(6Y"`W?gd03D)<Sn<#mkcc.]V^I00r3isP)b"5)qg%VCGV4jf&h/\ir@5c$;I2Ap;7I*<kL'g)Y0@cNA4Rok]aqfkCXR(chBKT=N_cMrQ0/>Aq*%&7bJND\!q7[VJ?"BE9@NXWek3n61;FB])HbY$WAQ.$+ahnGPTn39HN`+^PP)9.P-Pc>9@UkE`=b.MXfkXK5`(F1BgO.Dcf;<Qua;<R06^PH^-7eGNg2VG[TXW9K9j.=^mFR2b_D[-11nFE;j:;O@abrfhY2G]gmmCB>n4kN!8U8tF;hSB1B1c23,]:RYo<lMt_HZtLZ]d;sRY?iD;Bpd-II4Opef!c[i8sa4Y((<Ts<Oja=hDI60d*W)MF,Jr*`6u@t,%_*RXFQ?$A$dh(3;+:>JPheD4RBsVVc0P?mo[aCF.IV0CY?:dBnfpCM3o?,`<k[-8Sb`go3^76T!-T3C=%2SJq$`r1_e57\J/\!k+%fBk1\TRriS>9os9h;-dp<%.K>momU.A@qn!RHCQI(s4RMaf;bpmST@?sJp?t]fh'OLj&?3JaWK-FOh6,5^Z/!c-rh5)<.a>X+h+L1FmscnqLjf~>endstream
|
||||||
|
endobj
|
||||||
|
xref
|
||||||
|
0 11
|
||||||
|
0000000000 65535 f
|
||||||
|
0000000061 00000 n
|
||||||
|
0000000102 00000 n
|
||||||
|
0000000209 00000 n
|
||||||
|
0000000321 00000 n
|
||||||
|
0000000514 00000 n
|
||||||
|
0000000708 00000 n
|
||||||
|
0000000776 00000 n
|
||||||
|
0000001056 00000 n
|
||||||
|
0000001121 00000 n
|
||||||
|
0000004086 00000 n
|
||||||
|
trailer
|
||||||
|
<<
|
||||||
|
/ID
|
||||||
|
[<451d734656bfda21b00c95ac21a36c22><451d734656bfda21b00c95ac21a36c22>]
|
||||||
|
% ReportLab generated PDF document -- digest (opensource)
|
||||||
|
|
||||||
|
/Info 7 0 R
|
||||||
|
/Root 6 0 R
|
||||||
|
/Size 11
|
||||||
|
>>
|
||||||
|
startxref
|
||||||
|
6878
|
||||||
|
%%EOF
|
||||||
@@ -4,472 +4,442 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
|
||||||
<title>Chase Dumphord | Digital Systems & Infrastructure</title>
|
<title>Ced's NOC | Live Systems Dashboard</title>
|
||||||
|
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
content="Chase Dumphord portfolio - digital systems, infrastructure, networking, automation, homelab engineering, and real-world technical projects."
|
content="Ced's NOC — live network operations center dashboard showing real-time infrastructure health, service status, and edge system monitoring."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<link rel="stylesheet" href="style.css" />
|
<!-- Open Graph -->
|
||||||
|
<meta property="og:title" content="Ced's NOC | Live Systems Dashboard" />
|
||||||
|
<meta property="og:description" content="Live infrastructure visibility — Proxmox, K3s, TrueNAS, APRS edge systems." />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:url" content="https://noc.chasedumphord.com" />
|
||||||
|
|
||||||
|
<!-- Favicons (path up one level since we're in /noc/) -->
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="../assets/favicons/favicon-32x32.png" />
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="../assets/favicons/favicon-16x16.png" />
|
||||||
|
<link rel="icon" type="image/png" sizes="192x192" href="../assets/favicons/favicon-192x192.png" />
|
||||||
|
<link rel="apple-touch-icon" sizes="512x512" href="../assets/favicons/favicon-512x512.png" />
|
||||||
|
<link rel="shortcut icon" href="../assets/favicons/favicon.ico" />
|
||||||
|
|
||||||
|
<meta name="robots" content="index, follow" />
|
||||||
|
<meta name="author" content="Chase Dumphord" />
|
||||||
|
|
||||||
|
<!-- Fonts — same as main site -->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Syne:wght@700;800&family=DM+Sans:wght@400;500;700&display=swap" rel="stylesheet" />
|
||||||
|
|
||||||
|
<!-- Shared stylesheet (up one level) -->
|
||||||
|
<link rel="stylesheet" href="../style.css" />
|
||||||
|
|
||||||
|
<!-- NOC-specific styles -->
|
||||||
|
<style>
|
||||||
|
/* ── NOC page overrides & extras ── */
|
||||||
|
.noc-page-hero {
|
||||||
|
padding: 3.5rem 0 2rem;
|
||||||
|
border-bottom: 1px solid var(--line);
|
||||||
|
}
|
||||||
|
|
||||||
|
.noc-page-hero .eyebrow {
|
||||||
|
margin-bottom: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.noc-page-title {
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-size: clamp(2rem, 4vw, 3.2rem);
|
||||||
|
font-weight: 800;
|
||||||
|
margin: 0 0 0.75rem;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.noc-page-title span {
|
||||||
|
color: var(--accent-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.noc-page-lead {
|
||||||
|
color: var(--muted);
|
||||||
|
font-size: 1rem;
|
||||||
|
max-width: 60ch;
|
||||||
|
margin: 0 0 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.noc-page-meta {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.6rem 1.4rem;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.78rem;
|
||||||
|
color: var(--muted);
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.noc-page-meta a { color: var(--muted); }
|
||||||
|
.noc-page-meta a:hover { color: var(--accent-2); }
|
||||||
|
|
||||||
|
/* Full-width NOC content area */
|
||||||
|
.noc-full {
|
||||||
|
padding: 2.5rem 0 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Uptime summary bar */
|
||||||
|
.uptime-bar {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uptime-pill {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.76rem;
|
||||||
|
padding: 0.35rem 0.75rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
color: var(--muted);
|
||||||
|
background: rgba(255,255,255,0.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
.uptime-pill.online {
|
||||||
|
color: var(--accent-2);
|
||||||
|
border-color: rgba(94, 250, 204, 0.3);
|
||||||
|
background: rgba(94, 250, 204, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.uptime-pill.warning {
|
||||||
|
color: var(--warning);
|
||||||
|
border-color: rgba(242, 204, 96, 0.3);
|
||||||
|
background: rgba(242, 204, 96, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.uptime-pill.offline {
|
||||||
|
color: var(--danger);
|
||||||
|
border-color: rgba(255, 95, 86, 0.3);
|
||||||
|
background: rgba(255, 95, 86, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Layer filter tabs */
|
||||||
|
.layer-tabs {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-tab {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.76rem;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 0.35rem 0.85rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
color: var(--muted);
|
||||||
|
background: transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-tab:hover,
|
||||||
|
.layer-tab.active {
|
||||||
|
color: var(--accent-2);
|
||||||
|
border-color: rgba(94, 250, 204, 0.35);
|
||||||
|
background: rgba(94, 250, 204, 0.07);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Roadmap section on NOC page */
|
||||||
|
.noc-roadmap {
|
||||||
|
margin-top: 3rem;
|
||||||
|
padding-top: 2.5rem;
|
||||||
|
border-top: 1px solid var(--line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stack info footer on NOC page */
|
||||||
|
.noc-stack-bar {
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
padding: 1rem 1.25rem;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
background: rgba(0,0,0,0.2);
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.78rem;
|
||||||
|
color: var(--muted);
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem 1.5rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.noc-stack-bar strong {
|
||||||
|
color: var(--accent-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 620px) {
|
||||||
|
.layer-tabs { gap: 0.4rem; }
|
||||||
|
.layer-tab { font-size: 0.7rem; padding: 0.3rem 0.65rem; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
<!-- ═══════════════════════════════ NAV ═══════════════════════════════ -->
|
||||||
<header class="site-header">
|
<header class="site-header">
|
||||||
<div class="container nav">
|
<div class="container nav">
|
||||||
<a href="#top" class="logo">Chase Dumphord</a>
|
<a href="https://chasedumphord.com" class="logo">Ced<span class="logo-cursor">_</span></a>
|
||||||
|
|
||||||
<nav>
|
<nav>
|
||||||
<ul class="nav-links">
|
<ul class="nav-links">
|
||||||
<li><a href="#snapshot">Snapshot</a></li>
|
<li><a href="https://chasedumphord.com/#snapshot">Snapshot</a></li>
|
||||||
<li><a href="#noc">NOC</a></li>
|
<li><a href="https://chasedumphord.com/#about">About</a></li>
|
||||||
<li><a href="#about">About</a></li>
|
<li><a href="https://chasedumphord.com/#projects">Projects</a></li>
|
||||||
<li><a href="#projects">Projects</a></li>
|
<li><a href="https://chasedumphord.com/#stack">Stack</a></li>
|
||||||
<li><a href="#resume">Resume</a></li>
|
<li><a href="https://chasedumphord.com/#contact">Contact</a></li>
|
||||||
<li><a href="#contact">Contact</a></li>
|
<li><a href="https://chasedumphord.com/assets/images/ChaseD_Resume.pdf" target="_blank" rel="noopener noreferrer">Resume</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main id="top">
|
<main id="top">
|
||||||
<section class="hero">
|
|
||||||
<div class="container hero-grid">
|
|
||||||
<div class="hero-text">
|
|
||||||
<p class="eyebrow">Digital Systems • Infrastructure • Networking • Automation • Edge Systems</p>
|
|
||||||
|
|
||||||
<h1>I build practical systems that connect hardware, networks, software, and operations.</h1>
|
<!-- ═══════════════════════════════ NOC HERO ═══════════════════════════════ -->
|
||||||
|
<div class="noc-page-hero">
|
||||||
<p class="lead">
|
<div class="container">
|
||||||
I’m Chase Dumphord — a hands-on systems builder focused on digital infrastructure,
|
<p class="eyebrow">
|
||||||
Linux systems, homelab engineering, Raspberry Pi deployments, networking, automation,
|
<span class="eyebrow-dot"></span>
|
||||||
and real-world technical problem solving.
|
Ced's NOC • Live Infrastructure Dashboard • Auto-refresh: 30s
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="hero-actions">
|
<h1 class="noc-page-title">
|
||||||
<a class="btn btn-primary" href="#projects">View Projects</a>
|
Live Systems <span>Dashboard</span>
|
||||||
<a class="btn btn-secondary" href="#contact">Contact Me</a>
|
</h1>
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul class="quick-facts">
|
<p class="noc-page-lead">
|
||||||
<li>Oxford, MS</li>
|
Real-time visibility into Ced's HomeLab infrastructure — Proxmox, K3s,
|
||||||
<li>
|
TrueNAS, APRS RF edge systems, and self-hosted services.
|
||||||
GitHub:
|
Not simulated. Not a demo. Running hardware.
|
||||||
<a href="https://github.com/ced4568" target="_blank" rel="noopener noreferrer">ced4568</a>
|
</p>
|
||||||
</li>
|
|
||||||
<li>
|
<ul class="noc-page-meta">
|
||||||
Email:
|
<li>📍 Oxford, MS</li>
|
||||||
<a href="mailto:chasedumphord@gmail.com">[email protected]</a>
|
<li><a href="https://chasedumphord.com">← Portfolio</a></li>
|
||||||
</li>
|
<li><a href="https://github.com/ced4568" target="_blank" rel="noopener noreferrer">github/ced4568</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="hero-panel">
|
|
||||||
<img
|
|
||||||
src="assets/images/ChaseD_headshot.jpg"
|
|
||||||
alt="Headshot of Chase Dumphord"
|
|
||||||
class="hero-image"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div class="terminal-card">
|
|
||||||
<div class="terminal-top">
|
|
||||||
<span></span>
|
|
||||||
<span></span>
|
|
||||||
<span></span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<pre><code>$ whoami
|
<!-- ═══════════════════════════════ NOC DASHBOARD ═══════════════════════════════ -->
|
||||||
systems_builder
|
<div class="noc-full">
|
||||||
|
|
||||||
$ focus
|
|
||||||
infrastructure
|
|
||||||
networking
|
|
||||||
automation
|
|
||||||
edge_systems
|
|
||||||
|
|
||||||
$ status
|
|
||||||
building_real_systems</code></pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="snapshot" class="section section-alt">
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="section-heading">
|
|
||||||
<p class="section-label">Environment</p>
|
|
||||||
<h2>Systems Snapshot</h2>
|
|
||||||
<p class="section-intro">
|
|
||||||
A quick look at the infrastructure and systems I’m actively building and documenting.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stats-grid">
|
|
||||||
<div class="stat-card">
|
|
||||||
<h3>12+</h3>
|
|
||||||
<p>Nodes</p>
|
|
||||||
<span>K3s cluster environment</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stat-card">
|
|
||||||
<h3>10+</h3>
|
|
||||||
<p>Services</p>
|
|
||||||
<span>Self-hosted stack</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stat-card">
|
|
||||||
<h3>4</h3>
|
|
||||||
<p>VLANs</p>
|
|
||||||
<span>Segmented network design</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stat-card">
|
|
||||||
<h3>2</h3>
|
|
||||||
<p>iGate Nodes</p>
|
|
||||||
<span>Home + mobile APRS</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="noc" class="section noc-dashboard">
|
|
||||||
<div class="container">
|
|
||||||
<div class="section-heading">
|
|
||||||
<p class="section-label">Ced’s NOC</p>
|
|
||||||
<h2>Live Systems Overview</h2>
|
|
||||||
<p class="section-intro">
|
|
||||||
Real infrastructure inventory from Ced’s HomeLab, K3s cluster, and APRS edge systems.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<!-- Status command bar -->
|
||||||
<div class="noc-command-bar">
|
<div class="noc-command-bar">
|
||||||
<span class="status-dot"></span>
|
<span class="status-dot" id="noc-dot"></span>
|
||||||
<span id="noc-status-text">Loading NOC status...</span>
|
<span id="noc-status-text">Connecting to NOC feed...</span>
|
||||||
|
<span class="noc-refresh-badge" id="noc-refresh-badge"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="noc-proof">
|
<p class="noc-proof">
|
||||||
Built using real infrastructure: Proxmox • K3s • TrueNAS • VLAN segmentation • APRS RF Edge Systems
|
Proxmox • K3s • TrueNAS • VLAN Segmentation • APRS RF Edge Systems
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<!-- Uptime summary pills (populated by JS) -->
|
||||||
|
<div class="uptime-bar" id="uptime-bar"></div>
|
||||||
|
|
||||||
|
<!-- Metrics -->
|
||||||
<div class="noc-metrics-grid">
|
<div class="noc-metrics-grid">
|
||||||
<div class="noc-metric">
|
<div class="noc-metric">
|
||||||
<h3 id="metric-nodes">--</h3>
|
<h3 id="metric-nodes">--</h3>
|
||||||
<p>Infrastructure Nodes</p>
|
<p>Infrastructure Nodes</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="noc-metric">
|
<div class="noc-metric">
|
||||||
<h3 id="metric-services">--</h3>
|
<h3 id="metric-services">--</h3>
|
||||||
<p>Services Online</p>
|
<p>Services Online</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="noc-metric">
|
<div class="noc-metric">
|
||||||
<h3 id="metric-vlans">--</h3>
|
<h3 id="metric-vlans">--</h3>
|
||||||
<p>Network Segments</p>
|
<p>Network Segments</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="noc-metric">
|
<div class="noc-metric">
|
||||||
<h3 id="metric-edge">--</h3>
|
<h3 id="metric-edge">--</h3>
|
||||||
<p>Edge Systems</p>
|
<p>Edge Systems</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Alert panel -->
|
||||||
<div class="noc-alert-panel">
|
<div class="noc-alert-panel">
|
||||||
<div class="noc-alert-header">
|
<div class="noc-alert-header">
|
||||||
<h3>🚨 NOC Alert Panel</h3>
|
<h3>🚨 Alert Panel</h3>
|
||||||
<span>Top 3 System Notes</span>
|
<span>Top 3 Priority Systems</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="noc-alert-list" class="noc-alert-list">
|
<div id="noc-alert-list" class="noc-alert-list">
|
||||||
<p>Loading alerts...</p>
|
<p class="noc-loading">Awaiting data feed...</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Layer filter tabs -->
|
||||||
|
<div class="layer-tabs" id="layer-tabs">
|
||||||
|
<button class="layer-tab active" data-layer="all">All Systems</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- System cards grid -->
|
||||||
<div id="noc-system-grid" class="noc-system-grid"></div>
|
<div id="noc-system-grid" class="noc-system-grid"></div>
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="about" class="section">
|
<!-- Fallback -->
|
||||||
<div class="container">
|
<div id="noc-fallback" class="noc-fallback" style="display:none;">
|
||||||
<div class="section-heading">
|
<p class="noc-fallback-msg">
|
||||||
<p class="section-label">About</p>
|
📡 NOC feed unavailable from this context — systems run locally.<br/>
|
||||||
<h2>Hands-on systems builder with a digital infrastructure mindset</h2>
|
Data updates when the local pipeline pushes a fresh noc-status.json.
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="content-grid">
|
|
||||||
<div class="card">
|
|
||||||
<p>
|
|
||||||
I’m a technical professional focused on digital systems, infrastructure, networking,
|
|
||||||
automation, and hands-on system integration. I enjoy building systems that are practical,
|
|
||||||
reliable, and well documented — from homelab services and dashboards to Raspberry Pi
|
|
||||||
deployments, APRS iGates, and troubleshooting workflows.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
My background blends field engineering, industrial technology, software-oriented thinking,
|
|
||||||
and infrastructure problem solving. I’m especially interested in projects that connect the
|
|
||||||
physical and digital worlds through monitoring, networking, automation, and resilient design.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<!-- Stack info bar -->
|
||||||
<h3>Core Focus Areas</h3>
|
<div class="noc-stack-bar">
|
||||||
|
<span><strong>Stack:</strong> Python health checks → JSON → JS dashboard</span>
|
||||||
<ul class="clean-list">
|
<span><strong>Next:</strong> Grafana + Prometheus integration</span>
|
||||||
<li>Digital systems and infrastructure</li>
|
<span><strong>Source:</strong>
|
||||||
<li>Linux systems and service management</li>
|
<a href="https://github.com/ced4568/ceds-homelab" target="_blank" rel="noopener noreferrer">
|
||||||
<li>Networking, VLANs, failover, and connectivity troubleshooting</li>
|
github/ceds-homelab
|
||||||
<li>Raspberry Pi and edge-device deployments</li>
|
|
||||||
<li>Documentation, process building, and reproducible project design</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="projects" class="section section-alt">
|
|
||||||
<div class="container">
|
|
||||||
<div class="section-heading">
|
|
||||||
<p class="section-label">Projects</p>
|
|
||||||
<h2>🔧 Infrastructure & Systems Projects</h2>
|
|
||||||
<p class="section-intro">
|
|
||||||
These projects are built around real systems, networking, Linux services, edge devices,
|
|
||||||
and practical documentation.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="projects-grid">
|
|
||||||
<article class="project-card featured-project">
|
|
||||||
<div class="project-top">
|
|
||||||
<h3>🧠 Ced’s HomeLab Infrastructure</h3>
|
|
||||||
<span class="status-pill">Flagship</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p class="tags">Infrastructure • Networking • Virtualization • Monitoring • Self-Hosting</p>
|
|
||||||
|
|
||||||
<p class="project-impact">
|
|
||||||
Designed as a practical infrastructure environment for networking, monitoring,
|
|
||||||
service hosting, and documentation.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Personal infrastructure lab focused on network segmentation, virtualization,
|
|
||||||
self-hosted services, monitoring, and architecture documentation.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<ul class="clean-list">
|
|
||||||
<li>VLAN segmentation and network design</li>
|
|
||||||
<li>Proxmox virtualization</li>
|
|
||||||
<li>Self-hosted services and monitoring</li>
|
|
||||||
<li>System architecture documentation</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<a href="https://github.com/ced4568/ceds-homelab" target="_blank" rel="noopener noreferrer" class="project-link">
|
|
||||||
View Project →
|
|
||||||
</a>
|
</a>
|
||||||
</article>
|
</span>
|
||||||
|
|
||||||
<article class="project-card">
|
|
||||||
<div class="project-top">
|
|
||||||
<h3>☸️ K3s Kubernetes Cluster</h3>
|
|
||||||
<span class="status-pill">Infrastructure</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="tags">Kubernetes • Containers • Linux • Infrastructure • Automation</p>
|
<!-- NOC Roadmap -->
|
||||||
|
<div class="noc-roadmap">
|
||||||
<p class="project-impact">
|
<p class="section-label">// noc roadmap</p>
|
||||||
Built to simulate distributed infrastructure, container orchestration, and scalable service deployment.
|
<h2 class="section-h2" style="font-family:var(--font-display);font-size:1.6rem;margin:0 0 1.25rem;">Build Stages</h2>
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Multi-node K3s cluster built for container orchestration, service deployment,
|
|
||||||
and infrastructure experimentation.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<ul class="clean-list">
|
|
||||||
<li>Multi-node cluster setup</li>
|
|
||||||
<li>Containerized workloads</li>
|
|
||||||
<li>Service deployment</li>
|
|
||||||
<li>Infrastructure automation</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<a href="https://github.com/ced4568/ced-k3s-homelab" target="_blank" rel="noopener noreferrer" class="project-link">
|
|
||||||
View Project →
|
|
||||||
</a>
|
|
||||||
</article>
|
|
||||||
|
|
||||||
<article class="project-card">
|
|
||||||
<div class="project-top">
|
|
||||||
<h3>📡 APRS iGate System</h3>
|
|
||||||
<span class="status-pill">Edge System</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p class="tags">RF • Linux • Raspberry Pi • Networking • APRS-IS • Edge Systems</p>
|
|
||||||
|
|
||||||
<p class="project-impact">
|
|
||||||
Bridges RF communication into IP-based infrastructure using Linux, Direwolf, and APRS-IS.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Operational dual-node APRS iGate system built with Raspberry Pi, Direwolf, APRS-IS,
|
|
||||||
RF radios, HomeLab network integration, and planned mobile GPS support.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<ul class="clean-list">
|
|
||||||
<li>RF packet decoding with Direwolf</li>
|
|
||||||
<li>APRS-IS uplink verified on aprs.fi</li>
|
|
||||||
<li>HomeLab WiFi + mobile hotspot failover</li>
|
|
||||||
<li>Mobile build includes ETH-USB-HUB-BOX expansion</li>
|
|
||||||
<li>Documented configs, architecture, and troubleshooting</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<a href="https://github.com/ced4568/ceds-aprs-igate" target="_blank" rel="noopener noreferrer" class="project-link">
|
|
||||||
View Project →
|
|
||||||
</a>
|
|
||||||
</article>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="section noc-section">
|
|
||||||
<div class="container">
|
|
||||||
<div class="section-heading">
|
|
||||||
<p class="section-label">NOC Roadmap</p>
|
|
||||||
<h2>📊 Ced’s NOC Vision</h2>
|
|
||||||
<p class="section-intro">
|
|
||||||
Ced’s NOC is being built as a staged monitoring and systems-visibility platform for HomeLab,
|
|
||||||
Kubernetes, edge devices, and future production-style dashboards.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="noc-grid">
|
<div class="noc-grid">
|
||||||
<div class="noc-card">
|
<div class="noc-card">
|
||||||
<h3>✅ Current: Portfolio NOC</h3>
|
<div class="noc-card-badge done">✅ Live</div>
|
||||||
|
<h3>Portfolio NOC</h3>
|
||||||
<p>
|
<p>
|
||||||
JSON-driven dashboard that displays real inventory, online/offline checks, service labels,
|
JSON-driven dashboard showing real inventory, online/offline checks,
|
||||||
latency, and last-check timestamps.
|
service labels, latency, and last-check timestamps.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="noc-card">
|
<div class="noc-card">
|
||||||
<h3>⚙️ Next: Automated Data Updates</h3>
|
<div class="noc-card-badge next">⚙️ Next</div>
|
||||||
|
<h3>Automated Data Updates</h3>
|
||||||
<p>
|
<p>
|
||||||
Scheduled local script updates will refresh system status data automatically and push dashboard-ready
|
Scheduled scripts auto-refresh system status and push dashboard-ready
|
||||||
JSON into the portfolio.
|
JSON on a cron interval — no manual updates.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="noc-card">
|
<div class="noc-card">
|
||||||
<h3>📈 Future: Grafana + Prometheus</h3>
|
<div class="noc-card-badge future">📈 Future</div>
|
||||||
|
<h3>Grafana + Prometheus</h3>
|
||||||
<p>
|
<p>
|
||||||
Deeper monitoring stack for Proxmox, TrueNAS, K3s, Raspberry Pi nodes, Uptime Kuma,
|
Full observability stack for Proxmox, TrueNAS, K3s, Raspberry Pi,
|
||||||
and APRS edge systems.
|
Uptime Kuma, and APRS edge systems with real-time metrics.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="resume" class="section">
|
|
||||||
<div class="container">
|
|
||||||
<div class="section-heading">
|
|
||||||
<p class="section-label">Resume Snapshot</p>
|
|
||||||
<h2>Technical experience that bridges field work and digital systems</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="content-grid">
|
|
||||||
<div class="card">
|
|
||||||
<h3>What I Bring</h3>
|
|
||||||
|
|
||||||
<ul class="clean-list">
|
|
||||||
<li>Industrial and field-service technical experience</li>
|
|
||||||
<li>Linux, Raspberry Pi, and systems administration work</li>
|
|
||||||
<li>Networking, connectivity, and troubleshooting depth</li>
|
|
||||||
<li>Documentation, process building, and reproducible project design</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card">
|
|
||||||
<h3>Current Direction</h3>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
I’m positioning myself around digital systems, infrastructure, networking,
|
|
||||||
automation, and technical operations — especially roles where hands-on problem
|
|
||||||
solving and system integration matter.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
More detailed resume content will be added here as the portfolio grows.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="section section-alt personal-section">
|
|
||||||
<div class="container personal-grid">
|
|
||||||
<div class="personal-image-wrap">
|
|
||||||
<img
|
|
||||||
src="assets/images/lakephotopinkpants.png"
|
|
||||||
alt="Chase Dumphord standing by a fence with a lake view in the background"
|
|
||||||
class="personal-image"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card">
|
|
||||||
<p class="section-label">Personal Note</p>
|
|
||||||
<h2>Technical, curious, and always building</h2>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Outside of work, I enjoy electronics, self-hosting, coding, drones, radio, and
|
|
||||||
hands-on technical projects that push me to learn something useful. That curiosity
|
|
||||||
carries directly into the way I build and document systems.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="contact" class="section">
|
|
||||||
<div class="container">
|
|
||||||
<div class="section-heading">
|
|
||||||
<p class="section-label">Contact</p>
|
|
||||||
<h2>Let’s connect</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="contact-grid">
|
|
||||||
<div class="card">
|
|
||||||
<h3>Contact Info</h3>
|
|
||||||
|
|
||||||
<p>Email: <a href="mailto:[email protected]">[email protected]</a></p>
|
|
||||||
<p>Phone: <a href="tel:+16622142231">662-214-2231</a></p>
|
|
||||||
<p>Location: Oxford, MS</p>
|
|
||||||
<p>
|
|
||||||
GitHub:
|
|
||||||
<a href="https://github.com/ced4568" target="_blank" rel="noopener noreferrer">github.com/ced4568</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card">
|
|
||||||
<h3>What I’m Open To</h3>
|
|
||||||
|
|
||||||
<ul class="clean-list">
|
|
||||||
<li>Digital systems and infrastructure roles</li>
|
|
||||||
<li>Networking and technical operations work</li>
|
|
||||||
<li>Automation and monitoring projects</li>
|
|
||||||
<li>Projects involving hardware + software integration</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
<!-- ═══════════════════════════════ FOOTER ═══════════════════════════════ -->
|
||||||
<footer class="site-footer">
|
<footer class="site-footer">
|
||||||
<div class="container footer-content">
|
<div class="container footer-content">
|
||||||
<p>© <span data-year></span> Chase Dumphord</p>
|
<p>© <span data-year></span> Chase Dumphord — <span class="footer-mono">noc.chasedumphord.com</span></p>
|
||||||
<a href="#top" class="back-to-top">Back to top ↑</a>
|
<a href="#top" class="back-to-top">↑ back to top</a>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script src="script.js"></script>
|
<!-- Shared script (up one level) -->
|
||||||
|
<script src="../script.js"></script>
|
||||||
|
|
||||||
|
<!-- NOC page extras — layer filter tabs + uptime pills -->
|
||||||
|
<script>
|
||||||
|
// ── Layer filter tabs ──────────────────────────────────────────
|
||||||
|
// Populated after NOC data loads. Filters the system grid by layer.
|
||||||
|
let allSystems = [];
|
||||||
|
|
||||||
|
const originalLoad = window.loadNocStatus;
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
// Hook into data after the shared script loads it
|
||||||
|
const observer = new MutationObserver(() => {
|
||||||
|
const cards = document.querySelectorAll(".noc-system-card");
|
||||||
|
if (cards.length > 0) {
|
||||||
|
buildLayerTabs();
|
||||||
|
buildUptimePills();
|
||||||
|
observer.disconnect();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const grid = document.getElementById("noc-system-grid");
|
||||||
|
if (grid) observer.observe(grid, { childList: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
function buildLayerTabs() {
|
||||||
|
const cards = document.querySelectorAll(".noc-system-card");
|
||||||
|
const layers = new Set(["all"]);
|
||||||
|
|
||||||
|
cards.forEach(card => {
|
||||||
|
const layerEl = card.querySelector(".noc-system-top span:last-child");
|
||||||
|
if (layerEl) layers.add(layerEl.textContent.trim());
|
||||||
|
});
|
||||||
|
|
||||||
|
const tabContainer = document.getElementById("layer-tabs");
|
||||||
|
tabContainer.innerHTML = "";
|
||||||
|
|
||||||
|
layers.forEach(layer => {
|
||||||
|
const btn = document.createElement("button");
|
||||||
|
btn.className = "layer-tab" + (layer === "all" ? " active" : "");
|
||||||
|
btn.dataset.layer = layer;
|
||||||
|
btn.textContent = layer === "all" ? "All Systems" : layer;
|
||||||
|
btn.addEventListener("click", () => filterByLayer(layer, btn));
|
||||||
|
tabContainer.appendChild(btn);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterByLayer(layer, activeBtn) {
|
||||||
|
document.querySelectorAll(".layer-tab").forEach(t => t.classList.remove("active"));
|
||||||
|
activeBtn.classList.add("active");
|
||||||
|
|
||||||
|
document.querySelectorAll(".noc-system-card").forEach(card => {
|
||||||
|
if (layer === "all") {
|
||||||
|
card.style.display = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const layerEl = card.querySelector(".noc-system-top span:last-child");
|
||||||
|
card.style.display =
|
||||||
|
layerEl && layerEl.textContent.trim() === layer ? "" : "none";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildUptimePills() {
|
||||||
|
const bar = document.getElementById("uptime-bar");
|
||||||
|
if (!bar) return;
|
||||||
|
|
||||||
|
const cards = document.querySelectorAll(".noc-system-card");
|
||||||
|
let online = 0, warning = 0, offline = 0;
|
||||||
|
|
||||||
|
cards.forEach(card => {
|
||||||
|
const dot = card.querySelector(".mini-status");
|
||||||
|
if (!dot) return;
|
||||||
|
if (dot.classList.contains("online")) online++;
|
||||||
|
else if (dot.classList.contains("warning")) warning++;
|
||||||
|
else if (dot.classList.contains("offline")) offline++;
|
||||||
|
});
|
||||||
|
|
||||||
|
bar.innerHTML = `
|
||||||
|
<span class="uptime-pill online">● ${online} Online</span>
|
||||||
|
${warning > 0 ? `<span class="uptime-pill warning">● ${warning} Degraded</span>` : ""}
|
||||||
|
${offline > 0 ? `<span class="uptime-pill offline">● ${offline} Offline</span>` : ""}
|
||||||
|
<span class="uptime-pill">${online + warning + offline} Total Systems</span>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
const yearSpan = document.querySelector("[data-year]");
|
|
||||||
if (yearSpan) {
|
|
||||||
yearSpan.textContent = new Date().getFullYear();
|
|
||||||
}
|
|
||||||
|
|
||||||
loadNocStatus();
|
|
||||||
setInterval(loadNocStatus, 30000);
|
|
||||||
});
|
|
||||||
|
|
||||||
async function loadNocStatus() {
|
|
||||||
try {
|
|
||||||
const response = await fetch("data/noc-status.json");
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error: ${response.status}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
const statusText = document.getElementById("noc-status-text");
|
|
||||||
const nodes = document.getElementById("metric-nodes");
|
|
||||||
const services = document.getElementById("metric-services");
|
|
||||||
const vlans = document.getElementById("metric-vlans");
|
|
||||||
const edge = document.getElementById("metric-edge");
|
|
||||||
const grid = document.getElementById("noc-system-grid");
|
|
||||||
const alertList = document.getElementById("noc-alert-list");
|
|
||||||
|
|
||||||
if (!statusText || !nodes || !services || !vlans || !edge || !grid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
statusText.textContent = `${data.nocName} — ${data.status} — Last updated: ${data.lastUpdated}`;
|
|
||||||
|
|
||||||
animateMetric(nodes, data.summary.nodes);
|
|
||||||
animateMetric(services, data.summary.services);
|
|
||||||
animateMetric(vlans, data.summary.vlans);
|
|
||||||
animateMetric(edge, data.summary.edgeSystems);
|
|
||||||
|
|
||||||
grid.innerHTML = "";
|
|
||||||
|
|
||||||
data.systems.forEach((system) => {
|
|
||||||
const card = document.createElement("article");
|
|
||||||
card.className = "noc-system-card";
|
|
||||||
|
|
||||||
const status = system.status.toLowerCase();
|
|
||||||
|
|
||||||
const statusClass =
|
|
||||||
status.includes("online") || status.includes("operational")
|
|
||||||
? "online"
|
|
||||||
: status.includes("building") || status.includes("tuning") || status.includes("active")
|
|
||||||
? "warning"
|
|
||||||
: "offline";
|
|
||||||
|
|
||||||
card.innerHTML = `
|
|
||||||
<div class="noc-system-top">
|
|
||||||
<span class="mini-status ${statusClass}"></span>
|
|
||||||
<span>${system.layer}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="system-label">${system.label || "System"}</div>
|
|
||||||
|
|
||||||
<div class="severity-pill ${system.severity?.toLowerCase() || "unknown"}">
|
|
||||||
${system.severity || "Unknown"}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h3>${system.name}</h3>
|
|
||||||
<p>${system.type}</p>
|
|
||||||
<code>${system.address}</code>
|
|
||||||
|
|
||||||
<div class="system-meta">
|
|
||||||
<small>Status: ${system.status}</small>
|
|
||||||
<small>Latency: ${system.latency || "N/A"}</small>
|
|
||||||
<small>Last Check: ${system.lastCheck || "Manual"}</small>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
grid.appendChild(card);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (alertList) {
|
|
||||||
renderAlerts(data.systems, alertList);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
const statusText = document.getElementById("noc-status-text");
|
|
||||||
|
|
||||||
if (statusText) {
|
|
||||||
statusText.textContent = "Ced’s NOC data unavailable";
|
|
||||||
}
|
|
||||||
|
|
||||||
console.error("Failed to load NOC status:", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function animateMetric(element, value) {
|
|
||||||
element.classList.remove("metric-pop");
|
|
||||||
element.textContent = value;
|
|
||||||
|
|
||||||
void element.offsetWidth;
|
|
||||||
element.classList.add("metric-pop");
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderAlerts(systems, alertList) {
|
|
||||||
const priority = systems
|
|
||||||
.map((system) => {
|
|
||||||
const severity = (system.severity || "Unknown").toLowerCase();
|
|
||||||
const status = (system.status || "").toLowerCase();
|
|
||||||
|
|
||||||
let score = 0;
|
|
||||||
|
|
||||||
if (severity.includes("critical") || status.includes("offline")) {
|
|
||||||
score = 3;
|
|
||||||
} else if (severity.includes("degraded")) {
|
|
||||||
score = 2;
|
|
||||||
} else if (severity.includes("unknown")) {
|
|
||||||
score = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { ...system, score };
|
|
||||||
})
|
|
||||||
.filter((system) => system.score > 0)
|
|
||||||
.sort((a, b) => b.score - a.score)
|
|
||||||
.slice(0, 3);
|
|
||||||
|
|
||||||
if (priority.length === 0) {
|
|
||||||
alertList.innerHTML = `
|
|
||||||
<div class="noc-alert healthy">
|
|
||||||
<strong>All monitored systems healthy</strong>
|
|
||||||
<span>No critical or degraded systems detected.</span>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
alertList.innerHTML = priority
|
|
||||||
.map((system) => {
|
|
||||||
const alertClass =
|
|
||||||
system.score === 3 ? "critical" : system.score === 2 ? "degraded" : "unknown";
|
|
||||||
|
|
||||||
return `
|
|
||||||
<div class="noc-alert ${alertClass}">
|
|
||||||
<strong>${system.name}</strong>
|
|
||||||
<span>${system.severity || system.status} • ${system.layer} • ${system.latency || "N/A"}</span>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
})
|
|
||||||
.join("");
|
|
||||||
}
|
|
||||||