feat(site): add /contact page with operator Discord + email, footer link

Contact page (site footer -> Contact) with Discord sudogadget and
ukmesh@proton.me, plus an observer-onboarding blurb. Wired into
publicRoutes (sitemap: true), lazy-loaded ContactPage chunk, and the
shared SiteLayout footer (app + website surfaces). Re-baselined
website-live-manifest.json for the new website image (e5db6790).
This commit is contained in:
gadgethd
2026-08-09 02:45:59 +00:00
parent 119eaf529d
commit 47811106d2
5 changed files with 98 additions and 51 deletions
+9 -1
View File
@@ -9,7 +9,8 @@ export type PublicRouteComponent =
| 'open-source'
| 'stats'
| 'spam'
| 'topology';
| 'topology'
| 'contact';
export type PublicRouteDefinition = {
path: string;
@@ -28,6 +29,13 @@ export const PUBLIC_ROUTES: readonly PublicRouteDefinition[] = [
description: 'Real-time analytics for the UK MeshCore LoRa mesh network. Live packet feed, repeater coverage maps, network statistics, and install guides.',
sitemap: true,
},
{
path: '/contact',
component: 'contact',
title: 'Contact — UK Mesh Network',
description: 'Get in touch with the UK Mesh operator about the site, the network, or adding your observer station.',
sitemap: true,
},
{
path: '/install',
component: 'install',
+2
View File
@@ -19,6 +19,7 @@ import {
const App = lazy(() => import('./App.js').then(({ App: Component }) => ({ default: Component })));
const OpenSourcePage = lazy(() => import('./pages/OpenSourcePage.js').then(({ OpenSourcePage: Component }) => ({ default: Component })));
const StatsPage = lazy(() => import('./pages/StatsPage.js').then(({ StatsPage: Component }) => ({ default: Component })));
const ContactPage = lazy(() => import('./pages/ContactPage.js').then(({ ContactPage: Component }) => ({ default: Component })));
const OwnerPortalPage = lazy(() => import('./pages/OwnerPortalPage.js').then(({ OwnerPortalPage: Component }) => ({ default: Component })));
const UKLayout = lazy(() => import('./pages/ukmesh/UKLayout.js').then(({ UKLayout: Component }) => ({ default: Component })));
const UKHomePage = lazy(() => import('./pages/ukmesh/UKHomePage.js').then(({ UKHomePage: Component }) => ({ default: Component })));
@@ -43,6 +44,7 @@ const PUBLIC_ROUTE_ELEMENTS: Record<PublicRouteComponent, React.ReactElement> =
stats: <StatsPage />,
spam: <SpamPage />,
topology: <TopologyPage />,
contact: <ContactPage />,
};
const root = document.getElementById('root')!;
+33
View File
@@ -0,0 +1,33 @@
import React from 'react';
export const ContactPage: React.FC = () => (
<div className="site-content site-prose">
<section className="prose-section">
<h1>Contact</h1>
<p>
Questions about the site, the network, or joining as an observer? Get in touch
directly UK Mesh is run by one person and everything sent this way gets read.
</p>
</section>
<section className="prose-section">
<h2>Ways to reach me</h2>
<ul>
<li>
<strong>Discord:</strong> <code>sudogadget</code> best for quick questions about
the site, the mesh, or getting your observer station added.
</li>
<li>
<strong>Email:</strong> <a href="mailto:ukmesh@proton.me">ukmesh@proton.me</a> for
anything longer, or if you prefer email.
</li>
</ul>
</section>
<section className="prose-section">
<h2>Adding an observer</h2>
<p>
Want your station feeding the live map? Message me on Discord or email with your
node&apos;s name and public key and I&apos;ll get you set up with an account.
</p>
</section>
</div>
);
+2
View File
@@ -231,6 +231,8 @@ export const SiteLayout: React.FC<SiteLayoutProps> = ({
<span className="site-footer__sep">·</span>
<a href="https://meshcore.gg/" target="_blank" rel="noopener noreferrer">Discord</a>
<span className="site-footer__sep">·</span>
<Link to="/contact">Contact</Link>
<span className="site-footer__sep">·</span>
<Link to="/stats">Stats</Link>
<span className="site-footer__sep">·</span>
<Link to="/open-source">Open Source</Link>
+52 -50
View File
@@ -1,45 +1,46 @@
{
"captured": "2026-08-08T01:11:39Z",
"fileCount": 75,
"captured": "2026-08-09T02:45:51Z",
"fileCount": 77,
"files": {
"50x.html": "876766b4e80133fd490603e073d3567425b88794828a9292104244c9e40875ed",
"assets/App-C8Ome_t9.js": "e50cf599fd514fbe29f50fa7e6a16c803f99d2fa89e53d702e0830c7afb88cc1",
"assets/App-BDHUqBpQ.js": "e92a8d22c81f98a42472d8a9afc22992352a576328f18e861c27b169f794433d",
"assets/App-oN66RUc2.css": "f6224045099ed56d1220de566bb8ba78c67bd6563b85d51fc99db976cf95b075",
"assets/AreaChart-CYSMORwh.js": "f4ac734b8348f9611ee221c3337f5d53a6461234825a26ed95fd05c1a457d27e",
"assets/Combobox-BkNidtIq.js": "7e22d8e84145938f56034caedea53b0a101dcf1f1a332709efee2f6f6d534e47",
"assets/Dialog-BZsDpYJT.js": "6e1e2f8365b53f7171619b5a5cf2a45cb07b16e5257dde90b9bea5bb1375ccac",
"assets/Dialog-CoY0YOSQ.js": "c95001ae93cc8635f27c01878282d12155e227d4222b56a9f2a6c633905841b6",
"assets/LazyChartMount-CUxTORl5.js": "23025b3c287155080ca55d97702e7151ff149aba80a05f585f50fac8f3548318",
"assets/LineChart-CJDhOZ-E.js": "36a3daf4d2e44db7b6827c65d2172a3138faa265c0d8c1cd7b9c76bd152a0447",
"assets/MapLibreMap-Bj2PSBES.js": "0d27bfde796dfcf47ce5f60b4a4d84fcc4745d0a30cdef5d9de62a2534a69407",
"assets/NotFoundPage-B-9hpUfM.js": "1fe7148c8ee5a2bcbc36dacc487c780532fc0139dbccc25816eac5bd39c9c30d",
"assets/ObserverRegistrationForm-DbO2caGm.js": "7be2795bc5b2ed49680666647c3d60ef3e72d4bc1abf44f9ce601067ae9a647c",
"assets/OpenSourcePage-RLgMTh8M.js": "ec6cb76d5209d754f58cbe74fdae648fea32d348dd69d7d0145719f553f6376d",
"assets/AreaChart-BFNaPjhm.js": "41e6e2865440e2fcbc46b4bbd5ce333080c4fba610e5e0a2c2ffc17c7da0d05f",
"assets/Combobox-DiJLbHZc.js": "71eeb111ff985e4b248cb6a2515a5ab5616ef0b301e90637ac58b624ad41b7f6",
"assets/ContactPage-DM2PT1x0.js": "3447ccebe5f8e41bdf6fce49de6cab395ba435b38780d0d4403ae96624efdfeb",
"assets/Dialog-6_HczqBb.js": "39240a4bda2ded60124a85bce2b33f6b81a3147b2d26873fa70ebb8e4e27e03d",
"assets/Dialog-DqQyVuJi.js": "3929fec525d5a405d4741593efc70dd14c7165e2c2f0873819eecbb585e0f413",
"assets/LazyChartMount-mGp8aVaq.js": "8e07f51694fbaf7cc11fc258eb7e6f60ae330c11b1c84fb06bc9d3e3640c7f6b",
"assets/LineChart-ByEwhLQI.js": "dc544ea2f1f340a9a127edd10fc10d6f0b3d8888a6beefa13e0ebe9b14a1fae2",
"assets/MapLibreMap-C3GTskhB.js": "a395b9ab7228adaf2c5669579a43f7a17c082aa0e74031795fd69c1520c84885",
"assets/NotFoundPage-DafsNFhu.js": "b3acc801c13efc21e9862c3c44e4866a8d22004627fa8ab39578fbf5b2b600c7",
"assets/ObserverRegistrationForm-DrDw1aAf.js": "799dda93d0f9716876b7864dab25011814cd4339be9e93d91e5dc4f9a7f2dfe3",
"assets/OpenSourcePage-BoYeNBgV.js": "b3c08c24736252e742ff17ccaf88ded368a12109919810fcbadf767aaeaecc67",
"assets/OwnerPortalPage-C9R6jsV-.css": "86985def763aedb396d011d59ca458327793ad17451598aa2bb9b6696e5f65cf",
"assets/OwnerPortalPage-DK0O3Rvg.js": "5de124cf81ef3240c02f2a1e237d59f2fbf5263c0133ff736569d536a50e7e85",
"assets/PlannerComparison-De9P-Z5i.js": "22f616539d784336579770a751a57692a95a835314499408123fd2865c72823a",
"assets/OwnerPortalPage-DktWUGfG.js": "25fa3daee292651953b06e671cfd95c44a0bd376a670fa7d564f67c8794942c2",
"assets/PlannerComparison-C7-KF2PW.js": "f3ea4e221d753a2a910c32e9ea45e59fd1a6591eace6c03fe120dc3d4b777f83",
"assets/SpamTransparencyPage-Cgpd8zrF.css": "5c8a1ee75e8d7f49bb0d50d54a0bdfa025fb81555c7f66dce22b10fa716eef98",
"assets/SpamTransparencyPage-D6meliLN.js": "b42cf95ff41bd910616313fafbb208cb9eb30727e7fbff6b368a179ba2615308",
"assets/SpamTransparencyPage-DO7bbQ75.js": "27b3abab7b60b0dc6ece07fe3c75e4194f6d828c841c10f5d88c8c1ca2310e9a",
"assets/StatsPage-CIUCRYVb.css": "495410b180aa16341bfb5ed90c309eb039358861e2127bf11486c7c362521e22",
"assets/StatsPage-D1WHgykh.js": "55904bb743924efdfe898159ec601667a142820b27601e41fe7c63ebc810408f",
"assets/Tabs-DvZ5eDf6.js": "00e49980047ec485708b065f9c449d41a8166b99446c7e259b83815e12d2cf30",
"assets/TimelineControl-CIn7Arz_.js": "0af424fad6a0e7c5bca33f8389e5f953ddb35f277b01eadc27b16cd49f4e8a67",
"assets/TopologyPage-B4Fb11Mq.js": "8dac3a4079b636cd41702ae211fadef8d3e55e946d6214c2ba44eee4d224eea8",
"assets/StatsPage-w_c9TvLS.js": "23bf1a9f10bc2ce3e14ada731eb9487ee050217f6b601b0d5d8577616301f727",
"assets/Tabs-DcpL9NDM.js": "14bde0b803f9c80d64eef70b62cb69c234de756abd1708b1b51fad1ef3f51a22",
"assets/TimelineControl-DUAbGZes.js": "c6e21962043a91310277a457a3a3e29cde80266f2759b5c02acd9bf2b442041f",
"assets/TopologyPage-C_dXg6D1.js": "b27843e51a57d78b21065b66ec3745731752f161895163c49391d7a58f6b9e10",
"assets/TopologyPage-DW9RsZIy.css": "7dba796e8d9b2160956b8ad26278554bc45053f3ac9277b9f7f896415a2fe0a3",
"assets/UKBestPracticePage-BT-2RqxR.js": "c033632a77eed02d0c7704cc77a8219d6b7f8f36ea10e526bb5a98514d8c8a15",
"assets/UKCompanionPage-VJ9MO36g.js": "3e5bfebefed8fa7057e6ef627eb83e951db88cfcea2215198177e484d31ff751",
"assets/UKBestPracticePage-DgRPwcdw.js": "75f9aeccf5758414b6c61dbd4bdf0f3b2590e495f734dbb62d341ee8f4ea2bff",
"assets/UKCompanionPage-DuTEFyql.js": "db976b2d1fe02dccff13d8bb0ac74598e4ecd31ae78053578b0bc623a38bd732",
"assets/UKFeedPage-DPt7fUU5.css": "58ab284609abe5e7a0cac02f81d2467011228255c7403946b3e12fe3982fb098",
"assets/UKFeedPage-Doduv14K.js": "6bc305d200057de37b83ae0cb04894e88082d94e13744ada214107301a34e459",
"assets/UKHomePage-CDseD6kY.js": "6583ec3ca308cfd8c49b6978737b559587bf09afca0fb495de8936bd2bb4f532",
"assets/UKInstallPage-BFcNtZZl.js": "772c940dc769f570f265860162eb134091cf03241a8825ae4185d4deb12046b1",
"assets/UKLayout-cDIzTl2I.js": "7c88ea1c9e6ee119ccf3599c180b16d4b456de95ab6271b05b792a71b4fcf293",
"assets/UKFeedPage-Dhvf6Q7_.js": "1f6ee5a8a36a47ff343fee377ace319a51bc7009d43e146a7ace23f189e14671",
"assets/UKHomePage-DzCRoAXr.js": "ecdd0fb2ffe8d7a3f334ae133b1b84d69cdc6109e3c24cf0956ddf2b2dc0e4ed",
"assets/UKInstallPage-sk0SnePl.js": "b3ba44bcc98c8b82b4b61c6b1af6bac245e759234275ae80bec33f31e9201b86",
"assets/UKLayout-_LGUkuxa.js": "995fdc936b9227ef49b3912285172d1f1f45a6c80ca5a45b3ce1e8898b6186ab",
"assets/UKLayout-w8l9E6b_.css": "317d99439c3ef9c10ad49e2aa5beb4cea670c20217f83be2731b2de8a23c13a2",
"assets/UKRepeaterSearchPage-BLdN16Gc.js": "2f3fbf332462235be965053bf4d997d93a989bc51a3b6d2a9a2dd1e1b241cc00",
"assets/UKRepeaterSearchPage-DOW1_90L.js": "f6df495bc0e08b1a305ccdbeae2fb7865b8acfe3f72208fe257b88d4373fc777",
"assets/api-BfzueihH.js": "bef003f072283fd5e3f14b29890f7610adf3fb9808e8c6e700bd48d3e7a8bc87",
"assets/clsx-B-dksMZM.js": "c7b843bc2bba461110e5ddf916d9c40180a383804ce73658730ec46e5196d2fd",
"assets/generateCategoricalChart-C7roe_Wc.js": "c5783d3f4e67e6d15ce79333f4a32a1d0768da08b01a27f969dce1101543ea82",
"assets/index-BF1vRSvu.js": "0b8a4832d8c84012c04b5e907f4739b30a5c8e183fa8a3979c3a491aece7361d",
"assets/generateCategoricalChart-ptr00sIK.js": "294ebce958c4201501d3e0ea2563a9b287d83c675831fa025b9467edde7396be",
"assets/index-CLePEFXU.css": "9f24956a5ccfa13d7d8dce48cfb9ddfb621eb673b9d2e1f96d75306aae58805e",
"assets/index-CPOyfqd-.js": "85327dbb64ee615674fe6cc541ee819468227ed77641bdef045fcdbd6ed0e349",
"assets/mapConfig-CMrab3U4.js": "de4c64634f5577d3bd3ae27d19ddfdca53ca317b43f679436bca9a66a9b072b9",
"assets/maplibre-gl-DhHnEPbY.js": "7f1f5cd51316c56ca3e652d1d5e9859c6daf8e3ac03af29882b633591f5d16c8",
"assets/maplibre-gl-PhPnDjd-.css": "5942fdb20cfdad1ab1bda9f6a2b24a0c9ce814244cc6b4689750e31e768f258c",
@@ -47,39 +48,40 @@
"assets/react-CCXFnprz.js": "3f7df165326c8fab289dedc765a8750697de6e3826ef402791e1fdd27335dc59",
"assets/scopedCache-C2xaKdKb.js": "ea81db76671ec528f6d553ce3c79e9fada3c8885549e39708faab8eb7b654bc4",
"assets/site-BQ-PgjGR.js": "0125219201a343cc1910eab32e03defac0f15ac948d60f380d24b189cb1013d1",
"assets/useAppMessageHandler-CZTssoLj.js": "9e26420e5729b00aef7fde70440d9e516859abe3393499e43c41446f9f6a8b74",
"assets/useListState-CnxE4Jvv.js": "ad54bcad798b4dda767273581d2d12a304814cd00879f11410d3dbac6095edf5",
"assets/useNodes-BfypDh1A.js": "0adeb40641d5a2ae9f8d798f39f2a5987098036539507fd32b0e6857fee4b6eb",
"assets/useVisibilityPoll-qJ8fVL0m.js": "cdafdf57f7622397d9afff625ffa20674ba08a5400095b36f7fc9782bc030c21",
"assets/useWatchlist-BzTqBsU4.js": "012c8c4e9474a040d28842ca6041f24dc11bf583d9a4202f294d3c256cdff139",
"assets/useWebSocket-DXBGYbR_.js": "1f7915d506427c893f738befe896115684c379b15a2c675f1d0bb8cf11c6e9ae",
"assets/useAppMessageHandler-BlZFIY8L.js": "e651f484ab26c71b58960e5b948c465142244843f8486f0b9ff3afd17515ff8e",
"assets/useListState-B4ztgNPp.js": "66a5d50e64e13f3fe826fd6e443a0d4419cb7b7bfd18236a3655b906fa72ac08",
"assets/useNodes-C2RhVSMu.js": "1a26f65bad8a5ba0cc2a39bca323deb47adefca6d2b05af0c1cab9f4536236d2",
"assets/useVisibilityPoll-5SnlVyPV.js": "adf03f1ba1cd680ff742ce9811a4dfd6a800a0a1988d913ef420a4a29ed9d528",
"assets/useWatchlist-6aqKGo4t.js": "b9a54545230b58a6de682cfb590b42f43f94d0c2e21e407888f430f91ad468f8",
"assets/useWebSocket-D1VQ7VQJ.js": "d08f53038fc969c40b89612b9138c09acd28a8012d8300c2a6c60c93ec30ac6f",
"assets/vite-preload-ckwbz45p.js": "b1cf8db666a7d7bfc05e8f8c93c4536728e9d086bf6f0270fa1fd0e607491519",
"companion/index.html": "7ef3289414d7f55f5945521c316370edf58e70565661721a733819e7a6fd0812",
"docs/index.html": "1eb7dc33e0761abbff12dc03a3be93b9686872ae5946f1a1e099ecceaf71700a",
"companion/index.html": "d03f6dfe09d277aca87e24204324c8582ad0723cb48869f81cf9ab332f087e1f",
"contact/index.html": "c00383e324a18b81112d216cafcb96cde21b87341cda18291ab607db960677e2",
"docs/index.html": "113abc57971cf8748f55f3a806502eae4aa450bc0890cb34740b1bdbc67a6875",
"favicon-teesside.svg": "71e87888cc5929079909ffb5206d81b00bc0ddeefd0f10e53a3ec6196253dafc",
"favicon.svg": "b6a63bfd7b68a436af22fd0826813ce5ece262e12e401c25d498f1daa99f3173",
"feed/index.html": "1bc3b9d95541e3656e05fd865e32a568ba6a34d976406954d284f97d5dc93a40",
"feed/index.html": "d2de73b97b81e1934e4e50e95713615a2560df54c7d4efde128fb708b661f05c",
"fonts/OFL-Inter.txt": "5b9321a4298cfeb6b34354164a1c3afc3db114569984c502b9b35d988fd58c57",
"fonts/OFL-ShareTechMono.txt": "9d96f445b6e9c701428811d0177f894874f8d6f07ecc30d568c506542368f3ff",
"fonts/inter-latin.woff2": "3100e775e8616cd2611beecfa23a4263d7037586789b43f035236a2e6fbd4c62",
"fonts/share-tech-mono-latin.woff2": "41e6b9f297f7d9a2df2aaa274092f76d2f72711a15ca455f7f4f4f92caf16b72",
"index.html": "031e22032dbd699affb35ff6721d702efe5c5ebcbe12fb0275d47fe037893b8b",
"install/index.html": "14cbb601c7f68312a30678c4059c89f799fc1221c8ce854428979b11d85389de",
"login/index.html": "f498dd7f542467223c421acef4cd76949d1fed928390e63352cb6bc64b1cbc80",
"index.html": "569e60dd7e8d8890d2015a737b40115a6c406b08228d67a538b8410cf928c787",
"install/index.html": "5fb43b5966e9e4ccf4b175e98a6e5834015562f07507267335bc3c3eb6bd72b6",
"login/index.html": "94cace4a1f3900358f7f5c2bd6b3fb477a926c0baafa5e16789327c6b8b78e13",
"manifest.json": "10b409d4176794abea8626e2f6af2ec77cbef9b56795ed7bbbda71644447364b",
"og-image.png": "f074e5c54f616dbbe41fdea3e3555fdaa763861d0694450c94cdeadd9b5b271e",
"open-source/index.html": "d08636bec03ee241e32c7894831d3f8f807294f6e80e464720ca0a88b21a55c3",
"repeater/index.html": "30cdfa844aad4166324e90ec329c942e424a18acfbb66a54b9009067b9e0e3fe",
"open-source/index.html": "e7dbe5b9c642c228958b41cce5ad4fbc3a05388a77fce322a2bd46feee2c4e0d",
"repeater/index.html": "4796d395ae94479d63eda7c15652f2361134f6bd542b8e97c20a6536c205e745",
"robots.txt": "2e61167cf8099b06d73fa2e01ef396bc32ee4f5303da34bf46461216641c2aab",
"sitemap.xml": "52302483775c1701228438981cb9c238da0392da4da5062a8d1bba03020cf67e",
"spam/index.html": "741c118aef673cf27ecacdc85868510555518dc8405346fee8a7e0d3346076df",
"stats/index.html": "389e9ff6004f1a83b879df9bdf36f5d66ac74126975d55d0575106e3cd57e048",
"sitemap.xml": "77f90bbab57d040a51abb4791c32be0bbffd1059a16e417d37d4aa92ed5857a3",
"spam/index.html": "d10f1d8661a50e4b25c3f5de18f1165d12659504d5c06f4a1091063cb2612f5f",
"stats/index.html": "064cf000e292499b571a7ccdccdada997ce36267a89aef68c94c72461eead185",
"sw-runtime.js": "3c4f3fd64ef6984751ff52c8071c918bbc719234f3ae25250ea5cccb60c9f26f",
"sw.js": "4b1b59200c37f70e578c5fdff6e620b2977e23419365d758978c11b24e2266f2",
"topology/index.html": "7ef9c3237e6623165418690073e6cdac5d1a1d56407147bb20a0f1c8ffd0eb97"
"topology/index.html": "d5123722a3ba1e0168c2ca2f61147b66ec32c3fe59d3a4565fa0c4b9718ef14d"
},
"imageCreated": "2026-08-08T00:36:28.802846296Z",
"imageId": "sha256:0e37443ee557a66689de0fb64fc9541eb7ef7264b06bb98e9cdf80b22cd032b3",
"imageCreated": "2026-08-09T02:44:17.940070524Z",
"imageId": "sha256:e5db6790c3a4ea125bbd22a0d06afe87f0988922705be383ee65a9b32c1faee8",
"site": "ukmesh.com",
"sourceRevisionLabel": "5210aba5e37b928db3744057beb78f2c17f92263"
"sourceRevisionLabel": "f5a2a2b93acb58b726c6798b03721f13a6938cec"
}