Skip to content

Commit 472996c

Browse files
committed
Add Naming Standard v1.0 to Getting Started page
Infrastructure (Part 1) and Companion (Part 2) naming conventions with node type codes, city codes, landmark examples, companion format, do-not rules, and public key prefix links.
1 parent 5781c0d commit 472996c

File tree

1 file changed

+287
-2
lines changed

1 file changed

+287
-2
lines changed

src/app/start/page.tsx

Lines changed: 287 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { generateHowToSchema, meshCoreSetupHowTo } from "@/lib/schemas/howto";
88
export const metadata: Metadata = {
99
title: "Get Started with MeshCore",
1010
description: "Learn how to join the Denver mesh network. Hardware requirements, firmware setup guide, configuration instructions, and community resources.",
11-
keywords: ["MeshCore", "mesh network", "getting started", "Denver", "LoRa", "ESP32", "firmware", "setup guide", "tutorial"],
11+
keywords: ["MeshCore", "mesh network", "getting started", "Denver", "LoRa", "ESP32", "firmware", "setup guide", "tutorial", "naming standard", "node naming"],
1212
alternates: {
1313
canonical: '/start',
1414
},
@@ -277,6 +277,66 @@ const resources = [
277277
},
278278
];
279279

280+
// Naming Standard v1.0 data
281+
const infraNodeTypes = [
282+
{ code: "RC", description: "Core Repeater — Backbone. Mountain/tower. Battery backup." },
283+
{ code: "RD", description: "Distribution Rpt — Bridges core to edge. Suburban elevated." },
284+
{ code: "RE", description: "Edge Repeater — Rooftop/residential. Mains power OK." },
285+
{ code: "RM", description: "Mobile Repeater — Vehicle or temporary." },
286+
{ code: "T", description: "Room Server — Fixed location." },
287+
{ code: "TM", description: "Mobile Room — Location changes." },
288+
{ code: "TR", description: "Room + Repeat — Room server w/ repeat on." },
289+
{ code: "OB", description: "Observer — Listen-only/monitoring." },
290+
];
291+
292+
const infraExamples = [
293+
{ name: "CO-DENVER-CHSPARK-RC01", description: "Core rpt, Cheesman Park" },
294+
{ name: "CO-DENVER-SLOAN-RE01", description: "Edge rpt, Sloan\u2019s Lake" },
295+
{ name: "CO-LKWD-GRENMTN-RD01", description: "Dist rpt, Green Mtn" },
296+
{ name: "CO-REDROCKS-RC01", description: "Core rpt, Red Rocks (no city needed)" },
297+
{ name: "CO-DENVER-RINO-T01", description: "Room server, RiNo" },
298+
];
299+
300+
const cityCodes = [
301+
"DENVER", "AURORA", "LKWD", "ARVADA", "WSTMNR", "THRTON", "CENTL", "BROOM",
302+
"LTTN", "ENGL", "CMRCE", "GLDN", "BOULDR", "PARKER", "CSTLRK", "HGHLND",
303+
"CSPRGS", "LSVL", "LFAYTE",
304+
];
305+
306+
const landmarkExamples = [
307+
{ code: "CHSPARK", name: "Cheesman" },
308+
{ code: "SLOAN", name: "Sloan\u2019s" },
309+
{ code: "WSHPARK", name: "Wash Park" },
310+
{ code: "RINO", name: "RiNo" },
311+
{ code: "LODO", name: "LoDo" },
312+
{ code: "CAPHILL", name: "Cap Hill" },
313+
{ code: "UNION", name: "Union Station" },
314+
{ code: "COLFAX", name: "Colfax" },
315+
{ code: "REDRKS", name: "Red Rocks" },
316+
{ code: "CONFLU", name: "Confluence" },
317+
{ code: "16THST", name: "16th St" },
318+
{ code: "STAPLE", name: "Stapleton" },
319+
{ code: "DIA", name: "DIA" },
320+
{ code: "SPR+I25", name: "Speer & I-25" },
321+
];
322+
323+
const companionExamples = [
324+
{ name: "\u{1F47B} M3SHGH\u00D8ST 01", description: "Primary carry node" },
325+
{ name: "\u{1F47B} M3SHGH\u00D8ST 02", description: "Home base node" },
326+
{ name: "\u{1F47B} M3SHGH\u00D8ST 03", description: "Vehicle node" },
327+
{ name: "\u{1F43F}\uFE0F SQRLNUT 01", description: "Primary companion" },
328+
{ name: "\u{1F525} BURNR F4", description: "Companion (key prefix suffix)" },
329+
{ name: "\u{1F3D4}\uFE0F PKBAGGER 01", description: "Primary companion" },
330+
];
331+
332+
const companionDoNots = [
333+
"Use your real name",
334+
"Put hardware in the name",
335+
"Use different emojis per device \u2014 one emoji per person",
336+
"Take someone else\u2019s emoji",
337+
"Go over 23 characters",
338+
];
339+
280340
const breadcrumbData = generateBreadcrumbSchema([
281341
{ name: 'Home', url: 'https://denvermc.com' },
282342
{ name: 'Get Started', url: 'https://denvermc.com/start' },
@@ -318,6 +378,9 @@ export default function StartPage() {
318378
<a href="#setup" className="btn-outline">
319379
Setup Guide
320380
</a>
381+
<a href="#naming" className="btn-outline">
382+
Naming Standard
383+
</a>
321384
</div>
322385
</div>
323386
</section>
@@ -587,8 +650,230 @@ export default function StartPage() {
587650
</div>
588651
</section>
589652

653+
{/* Naming Standard */}
654+
<section id="naming" className="px-6 py-16 bg-background-secondary">
655+
<div className="max-w-4xl mx-auto">
656+
<h2 className="text-3xl md:text-4xl font-bold mb-4 text-foreground text-center">
657+
Naming Standard
658+
</h2>
659+
<p className="text-foreground-muted text-center mb-12 max-w-2xl mx-auto">
660+
All MeshCore node names are limited to <span className="text-mesh font-semibold">23 characters</span> — this is a hard limit in the firmware. Follow the conventions below so the network stays organized and readable.
661+
</p>
662+
663+
{/* Part 1: Infrastructure Nodes */}
664+
<div className="mb-16">
665+
<h3 className="text-2xl font-bold text-foreground mb-6 flex items-center gap-3">
666+
<span className="text-3xl">📡</span>
667+
Part 1: Infrastructure Nodes
668+
</h3>
669+
670+
{/* Format Card */}
671+
<div className="card-mesh p-6 mb-8">
672+
<p className="font-mono text-lg text-mesh mb-4 text-center">
673+
CO-[CITY]-[LANDMARK]-[TYPE][##]
674+
</p>
675+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 text-sm text-foreground-muted">
676+
<div><span className="font-semibold text-foreground">CO</span> — State prefix (Colorado)</div>
677+
<div><span className="font-semibold text-foreground">CITY</span> — City code from the list below</div>
678+
<div><span className="font-semibold text-foreground">LANDMARK</span> — Recognizable location</div>
679+
<div><span className="font-semibold text-foreground">TYPE</span> — Node type code</div>
680+
<div><span className="font-semibold text-foreground">##</span> — Two-digit sequence number</div>
681+
</div>
682+
<p className="text-sm text-foreground-muted mt-4">
683+
When the landmark is prominent enough on its own (e.g., Red Rocks), you can drop CITY — the landmark gets up to 14 characters.
684+
</p>
685+
</div>
686+
687+
{/* Infrastructure Examples Table */}
688+
<div className="card-mesh overflow-hidden mb-8">
689+
<table className="w-full">
690+
<thead className="bg-night-800/50">
691+
<tr>
692+
<th className="px-6 py-3 text-left text-sm font-semibold text-foreground">Name</th>
693+
<th className="px-6 py-3 text-left text-sm font-semibold text-foreground">Description</th>
694+
</tr>
695+
</thead>
696+
<tbody className="divide-y divide-card-border">
697+
{infraExamples.map((ex) => (
698+
<tr key={ex.name} className="hover:bg-night-800/30 transition-colors">
699+
<td className="px-6 py-3 font-mono text-mesh text-sm">{ex.name}</td>
700+
<td className="px-6 py-3 text-foreground-muted text-sm">{ex.description}</td>
701+
</tr>
702+
))}
703+
</tbody>
704+
</table>
705+
</div>
706+
707+
{/* Node Type Codes Table */}
708+
<h4 className="text-lg font-semibold text-foreground mb-3">Node Type Codes</h4>
709+
<div className="card-mesh overflow-hidden mb-8">
710+
<table className="w-full">
711+
<thead className="bg-night-800/50">
712+
<tr>
713+
<th className="px-6 py-3 text-left text-sm font-semibold text-foreground">Code</th>
714+
<th className="px-6 py-3 text-left text-sm font-semibold text-foreground">Description</th>
715+
</tr>
716+
</thead>
717+
<tbody className="divide-y divide-card-border">
718+
{infraNodeTypes.map((type) => (
719+
<tr key={type.code} className="hover:bg-night-800/30 transition-colors">
720+
<td className="px-6 py-3 font-mono font-semibold text-mountain-500">{type.code}</td>
721+
<td className="px-6 py-3 text-foreground-muted text-sm">{type.description}</td>
722+
</tr>
723+
))}
724+
</tbody>
725+
</table>
726+
</div>
727+
728+
{/* City Codes Grid */}
729+
<h4 className="text-lg font-semibold text-foreground mb-3">City Codes</h4>
730+
<div className="card-mesh p-6 mb-8">
731+
<div className="grid grid-cols-2 md:grid-cols-4 gap-2">
732+
{cityCodes.map((code) => (
733+
<span key={code} className="font-mono text-sm text-mesh bg-night-800/30 px-3 py-1.5 rounded text-center">
734+
{code}
735+
</span>
736+
))}
737+
</div>
738+
<p className="text-sm text-foreground-muted mt-4">
739+
Don&apos;t see your city? Propose a code in{" "}
740+
<a href="https://discord.gg/QpaW8FTTCE" className="text-mesh hover:text-mesh-light">
741+
our Discord
742+
</a>.
743+
</p>
744+
</div>
745+
746+
{/* Landmark Examples Grid */}
747+
<h4 className="text-lg font-semibold text-foreground mb-3">Landmark Examples</h4>
748+
<div className="card-mesh p-6 mb-8">
749+
<div className="grid grid-cols-2 md:grid-cols-4 gap-2">
750+
{landmarkExamples.map((lm) => (
751+
<div key={lm.code} className="text-sm">
752+
<span className="font-mono text-mesh">{lm.code}</span>
753+
<span className="text-foreground-muted"> {lm.name}</span>
754+
</div>
755+
))}
756+
</div>
757+
</div>
758+
759+
{/* Public Key Prefixes Card */}
760+
<div className="card-mesh p-6">
761+
<div className="flex items-center gap-3 mb-3">
762+
<span className="text-3xl">🔑</span>
763+
<h4 className="text-lg font-semibold text-foreground">Public Key Prefixes</h4>
764+
</div>
765+
<p className="text-foreground-muted text-sm mb-4">
766+
Repeaters and room servers should use a unique public key prefix to avoid collisions. Check current prefix utilization and generate a key with a chosen prefix.
767+
</p>
768+
<div className="flex flex-wrap gap-3">
769+
<a
770+
href="https://analyzer.letsmesh.net/nodes/prefix-utilization"
771+
target="_blank"
772+
rel="noopener noreferrer"
773+
className="text-mesh hover:text-mesh-light inline-flex items-center gap-1 text-sm"
774+
>
775+
Check Prefix Utilization
776+
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
777+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
778+
</svg>
779+
</a>
780+
<a
781+
href="https://gessaman.com/mc-keygen/"
782+
target="_blank"
783+
rel="noopener noreferrer"
784+
className="text-mesh hover:text-mesh-light inline-flex items-center gap-1 text-sm"
785+
>
786+
Key Generator
787+
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
788+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
789+
</svg>
790+
</a>
791+
</div>
792+
</div>
793+
</div>
794+
795+
{/* Part 2: Companion Nodes */}
796+
<div>
797+
<h3 className="text-2xl font-bold text-foreground mb-6 flex items-center gap-3">
798+
<span className="text-3xl">📱</span>
799+
Part 2: Companion Nodes
800+
</h3>
801+
802+
{/* Format Card */}
803+
<div className="card-mesh p-6 mb-8">
804+
<p className="font-mono text-lg text-mesh mb-4 text-center">
805+
[EMOJI] [HANDLE] [##]
806+
</p>
807+
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3 text-sm text-foreground-muted">
808+
<div><span className="font-semibold text-foreground">EMOJI</span> — Your personal emoji (one per person)</div>
809+
<div><span className="font-semibold text-foreground">HANDLE</span> — Your unique handle/callsign</div>
810+
<div><span className="font-semibold text-foreground">##</span> — Number by purpose, not hardware</div>
811+
</div>
812+
<p className="text-sm text-foreground-muted mt-4">
813+
Number by purpose (01 = primary carry, 02 = home base, 03 = vehicle), not by hardware model. If you upgrade your radio, the name stays the same.
814+
</p>
815+
</div>
816+
817+
{/* Companion Examples Table */}
818+
<div className="card-mesh overflow-hidden mb-8">
819+
<table className="w-full">
820+
<thead className="bg-night-800/50">
821+
<tr>
822+
<th className="px-6 py-3 text-left text-sm font-semibold text-foreground">Name</th>
823+
<th className="px-6 py-3 text-left text-sm font-semibold text-foreground">Description</th>
824+
</tr>
825+
</thead>
826+
<tbody className="divide-y divide-card-border">
827+
{companionExamples.map((ex) => (
828+
<tr key={ex.name} className="hover:bg-night-800/30 transition-colors">
829+
<td className="px-6 py-3 font-mono text-mesh text-sm">{ex.name}</td>
830+
<td className="px-6 py-3 text-foreground-muted text-sm">{ex.description}</td>
831+
</tr>
832+
))}
833+
</tbody>
834+
</table>
835+
</div>
836+
837+
{/* Do Not Rules */}
838+
<div className="card-mesh overflow-hidden mb-8">
839+
<div className="p-6 bg-sunset-500/10 border-b border-card-border">
840+
<h4 className="text-lg font-semibold text-sunset-700 flex items-center gap-3">
841+
<span className="text-xl">⚠️</span>
842+
Do Not
843+
</h4>
844+
</div>
845+
<div className="p-6">
846+
<ul className="space-y-2">
847+
{companionDoNots.map((rule, index) => (
848+
<li key={index} className="text-foreground-muted flex items-start gap-2">
849+
<span className="text-sunset-500 mt-1"></span>
850+
<span>{rule}</span>
851+
</li>
852+
))}
853+
</ul>
854+
</div>
855+
</div>
856+
857+
{/* Community Tracking Card */}
858+
<div className="card-mesh p-6">
859+
<div className="flex items-center gap-3 mb-3">
860+
<span className="text-3xl">📋</span>
861+
<h4 className="text-lg font-semibold text-foreground">Community Tracking</h4>
862+
</div>
863+
<p className="text-foreground-muted text-sm">
864+
Before deploying a new node, check the shared community list to avoid duplicate names and emoji conflicts. Post your new node in{" "}
865+
<a href="https://discord.gg/QpaW8FTTCE" className="text-mesh hover:text-mesh-light">
866+
our Discord
867+
</a>{" "}
868+
so others can update their records.
869+
</p>
870+
</div>
871+
</div>
872+
</div>
873+
</section>
874+
590875
{/* Advanced Topics */}
591-
<section id="advanced" className="px-6 py-16 bg-background-secondary">
876+
<section id="advanced" className="px-6 py-16">
592877
<div className="max-w-6xl mx-auto">
593878
<h2 className="text-3xl md:text-4xl font-bold mb-4 text-foreground text-center">
594879
Advanced Topics

0 commit comments

Comments
 (0)