{ ["notes"] = entries };
+var json = System.Text.Json.JsonSerializer.Serialize(index, new System.Text.Json.JsonSerializerOptions
+{
+ WriteIndented = true
+});
+
+var indexPath = Path.Combine(Path.GetDirectoryName(dstDir)!, "notes-index.json");
+File.WriteAllText(indexPath, json);
+
+Console.WriteLine($"Copied {entries.Count} notes.");
+Console.WriteLine($"Index written to: {indexPath}");
+return 0;
+
+static string Slugify(string name)
+{
+ var slug = name.ToLowerInvariant()
+ .Replace("'", "")
+ .Replace(".", "")
+ .Replace("(", "")
+ .Replace(")", "");
+ slug = Regex.Replace(slug, @"[^a-z0-9 -]", "");
+ slug = Regex.Replace(slug, @"\s+", "-");
+ slug = Regex.Replace(slug, @"-+", "-");
+ return slug.Trim('-');
+}
+
+static string? FindContainingDir(string startDir, string markerFile)
+{
+ var dir = new DirectoryInfo(startDir);
+ while (dir != null)
+ {
+ if (File.Exists(Path.Combine(dir.FullName, markerFile)))
+ return dir.FullName;
+ dir = dir.Parent;
+ }
+ return null;
+}
+
diff --git a/ET/ET.sln b/ET/ET.sln
index cc08319..c94b85a 100644
--- a/ET/ET.sln
+++ b/ET/ET.sln
@@ -2,6 +2,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web", "Web\Web.csproj", "{6E375519-4DF8-455B-9AEC-0C84C31106E9}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Console", "Console\Console.csproj", "{A5946F7D-E8CE-4ACE-8D79-0F5FF0CB11C0}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -12,5 +14,9 @@ Global
{6E375519-4DF8-455B-9AEC-0C84C31106E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6E375519-4DF8-455B-9AEC-0C84C31106E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6E375519-4DF8-455B-9AEC-0C84C31106E9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A5946F7D-E8CE-4ACE-8D79-0F5FF0CB11C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A5946F7D-E8CE-4ACE-8D79-0F5FF0CB11C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A5946F7D-E8CE-4ACE-8D79-0F5FF0CB11C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A5946F7D-E8CE-4ACE-8D79-0F5FF0CB11C0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/ET/Web/Layout/MainLayout.razor b/ET/Web/Layout/MainLayout.razor
index 3abdcd9..fdc3d5d 100644
--- a/ET/Web/Layout/MainLayout.razor
+++ b/ET/Web/Layout/MainLayout.razor
@@ -2,14 +2,8 @@
-
-
-
@Body
diff --git a/ET/Web/Layout/NavMenu.razor b/ET/Web/Layout/NavMenu.razor
index a2979ef..6525fc7 100644
--- a/ET/Web/Layout/NavMenu.razor
+++ b/ET/Web/Layout/NavMenu.razor
@@ -16,17 +16,7 @@
Home
-
-
- Counter
-
-
-
-
- Weather
-
-
-
+
@if (groupedNotes == null)
{
Loading...
diff --git a/ET/Web/Pages/Counter.razor b/ET/Web/Pages/Counter.razor
deleted file mode 100644
index 372905f..0000000
--- a/ET/Web/Pages/Counter.razor
+++ /dev/null
@@ -1,19 +0,0 @@
-@page "/counter"
-
-Counter
-
-Counter
-
-Current count: @currentCount
-
-
-
-@code {
- private int currentCount = 0;
-
- private void IncrementCount()
- {
- currentCount++;
- }
-
-}
\ No newline at end of file
diff --git a/ET/Web/Pages/Weather.razor b/ET/Web/Pages/Weather.razor
deleted file mode 100644
index be9adb1..0000000
--- a/ET/Web/Pages/Weather.razor
+++ /dev/null
@@ -1,60 +0,0 @@
-@page "/weather"
-@inject HttpClient Http
-
-Weather
-
-Weather
-
-This component demonstrates fetching data from the server.
-
-@if (forecasts == null)
-{
-
- Loading...
-
-}
-else
-{
-
-
-
- | Date |
- Temp. (C) |
- Temp. (F) |
- Summary |
-
-
-
- @foreach (var forecast in forecasts)
- {
-
- | @forecast.Date.ToShortDateString() |
- @forecast.TemperatureC |
- @forecast.TemperatureF |
- @forecast.Summary |
-
- }
-
-
-}
-
-@code {
- private WeatherForecast[]? forecasts;
-
- protected override async Task OnInitializedAsync()
- {
- forecasts = await Http.GetFromJsonAsync("sample-data/weather.json");
- }
-
- public class WeatherForecast
- {
- public DateOnly Date { get; set; }
-
- public int TemperatureC { get; set; }
-
- public string? Summary { get; set; }
-
- public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
- }
-
-}
\ No newline at end of file
diff --git a/ET/Web/SyncDocs.ps1 b/ET/Web/SyncDocs.ps1
deleted file mode 100644
index 580f59e..0000000
--- a/ET/Web/SyncDocs.ps1
+++ /dev/null
@@ -1,35 +0,0 @@
-$src = Resolve-Path "$PSScriptRoot\..\..\docs\Notes"
-$dst = "$PSScriptRoot\wwwroot\docs\notes"
-if (Test-Path $dst) { Remove-Item "$dst\*" -Force -ErrorAction SilentlyContinue }
-New-Item -ItemType Directory -Path $dst -Force | Out-Null
-
-$entries = @()
-Get-ChildItem -Path $src -Filter "*.md" | ForEach-Object {
- $base = $_.BaseName
- $slug = $base.ToLowerInvariant()
- $slug = $slug -replace "'", ""
- $slug = $slug -replace "\.", ""
- $slug = $slug -replace "[^a-z0-9 -]", ""
- $slug = $slug -replace "\s+", "-"
- $slug = $slug -replace "-+", "-"
- $slug = $slug.Trim('-')
-
- Copy-Item $_.FullName (Join-Path $dst "$slug.md")
-
- $category = $null
- $content = Get-Content $_.FullName -Raw
- if ($content -match '(?s)^---\s*\n(.*?)\n---') {
- $frontmatter = $Matches[1]
- if ($frontmatter -match '(?m)^category:\s*(.+)$') {
- $category = $Matches[1].Trim().Trim('"')
- }
- }
-
- $entry = @{ slug = $slug; title = $base }
- if ($category) { $entry.category = $category }
- $entries += $entry
-}
-
-$indexPath = "$PSScriptRoot\wwwroot\docs\notes-index.json"
-$index = @{ notes = $entries } | ConvertTo-Json
-Set-Content -Path $indexPath -Value $index -Encoding UTF8
diff --git a/ET/Web/Web.csproj b/ET/Web/Web.csproj
index 071f3f1..f719c9a 100644
--- a/ET/Web/Web.csproj
+++ b/ET/Web/Web.csproj
@@ -14,7 +14,7 @@
-
+
diff --git a/ET/Web/wwwroot/docs/notes-index.json b/ET/Web/wwwroot/docs/notes-index.json
index 2fe084d..e604b33 100644
--- a/ET/Web/wwwroot/docs/notes-index.json
+++ b/ET/Web/wwwroot/docs/notes-index.json
@@ -1,422 +1,422 @@
-{
- "notes": [
- {
- "title": "Artificer",
- "category": "Role",
- "slug": "artificer"
- },
- {
- "slug": "awareness",
- "title": "Awareness"
- },
- {
- "title": "Cache Map",
- "category": "Gear",
- "slug": "cache-map"
- },
- {
- "slug": "card-library",
- "title": "Card Library"
- },
- {
- "title": "Concoliator",
- "category": "Role",
- "slug": "concoliator"
- },
- {
- "slug": "contents",
- "title": "Contents"
- },
- {
- "slug": "crisis-markers",
- "title": "Crisis Markers"
- },
- {
- "slug": "crisis-resolution",
- "title": "Crisis Resolution"
- },
- {
- "slug": "crisis",
- "title": "Crisis"
- },
- {
- "slug": "dirt-roads",
- "title": "Dirt Roads"
- },
- {
- "title": "Dolewood Canoe",
- "category": "Gear",
- "slug": "dolewood-canoe"
- },
- {
- "title": "E.03",
- "category": "Event",
- "slug": "e03"
- },
- {
- "slug": "ecology",
- "title": "Ecology"
- },
- {
- "slug": "endeavor-tokens",
- "title": "Endeavor Tokens"
- },
- {
- "slug": "energy-tokens",
- "title": "Energy Tokens"
- },
- {
- "slug": "event-cards",
- "title": "Event Cards"
- },
- {
- "slug": "events",
- "title": "Events"
- },
- {
- "slug": "explore-phase",
- "title": "Explore Phase"
- },
- {
- "title": "Explorer",
- "category": "Role",
- "slug": "explorer"
- },
- {
- "title": "Ferinodex",
- "category": "Gear",
- "slug": "ferinodex"
- },
- {
- "slug": "flora-meeples",
- "title": "Flora Meeples"
- },
- {
- "title": "Forest 1",
- "category": "Region",
- "slug": "forest-1"
- },
- {
- "title": "Forest 2",
- "category": "Region",
- "slug": "forest-2"
- },
- {
- "title": "Forest 3",
- "category": "Region",
- "slug": "forest-3"
- },
- {
- "title": "Forest 4",
- "category": "Region",
- "slug": "forest-4"
- },
- {
- "title": "Forest 5",
- "category": "Region",
- "slug": "forest-5"
- },
- {
- "slug": "forest",
- "title": "Forest"
- },
- {
- "title": "Gauzeblade",
- "category": "Gear",
- "slug": "gauzeblade"
- },
- {
- "slug": "gear-cards",
- "title": "Gear Cards"
- },
- {
- "title": "Grass 1",
- "category": "Region",
- "slug": "grass-1"
- },
- {
- "title": "Grass 2",
- "category": "Region",
- "slug": "grass-2"
- },
- {
- "title": "Grass 3",
- "category": "Region",
- "slug": "grass-3"
- },
- {
- "title": "Grass 4",
- "category": "Region",
- "slug": "grass-4"
- },
- {
- "title": "Grass 5",
- "category": "Region",
- "slug": "grass-5"
- },
- {
- "slug": "grasslands",
- "title": "Grasslands"
- },
- {
- "title": "Guide",
- "category": "Role",
- "slug": "guide"
- },
- {
- "title": "Hidden Trail Map",
- "category": "Gear",
- "slug": "hidden-trail-map"
- },
- {
- "slug": "injury-cards",
- "title": "Injury Cards"
- },
- {
- "slug": "lake",
- "title": "Lake"
- },
- {
- "slug": "losing-the-game",
- "title": "Losing the Game"
- },
- {
- "slug": "market",
- "title": "Market"
- },
- {
- "title": "Mountain 1",
- "category": "Region",
- "slug": "mountain-1"
- },
- {
- "title": "Mountain 2",
- "category": "Region",
- "slug": "mountain-2"
- },
- {
- "title": "Mountain 3",
- "category": "Region",
- "slug": "mountain-3"
- },
- {
- "title": "Mountain 4",
- "category": "Region",
- "slug": "mountain-4"
- },
- {
- "title": "Mountain 5",
- "category": "Region",
- "slug": "mountain-5"
- },
- {
- "slug": "mountain",
- "title": "Mountain"
- },
- {
- "title": "Paratrepsis Whistle",
- "category": "Gear",
- "slug": "paratrepsis-whistle"
- },
- {
- "slug": "paved-roads",
- "title": "Paved Roads"
- },
- {
- "title": "Perfect Day 1",
- "category": "Event",
- "slug": "perfect-day-1"
- },
- {
- "title": "Phonoscopic Headset",
- "category": "Gear",
- "slug": "phonoscopic-headset"
- },
- {
- "slug": "player-boards",
- "title": "Player Boards"
- },
- {
- "slug": "player-meeples",
- "title": "Player Meeples"
- },
- {
- "slug": "predator-meeples",
- "title": "Predator Meeples"
- },
- {
- "slug": "prepare-phase",
- "title": "Prepare Phase"
- },
- {
- "slug": "press-on",
- "title": "Press On"
- },
- {
- "slug": "prey-meeples",
- "title": "Prey Meeples"
- },
- {
- "slug": "progress",
- "title": "Progress"
- },
- {
- "slug": "ranger-badges",
- "title": "Ranger Badges"
- },
- {
- "slug": "ranger-meeples",
- "title": "Ranger Meeples"
- },
- {
- "slug": "research-station",
- "title": "Research Station"
- },
- {
- "slug": "rest",
- "title": "Rest"
- },
- {
- "slug": "role-cards",
- "title": "Role Cards"
- },
- {
- "slug": "round",
- "title": "Round"
- },
- {
- "title": "Ruins Map",
- "category": "Gear",
- "slug": "ruins-map"
- },
- {
- "slug": "scout",
- "title": "Scout"
- },
- {
- "title": "Shaper",
- "category": "Role",
- "slug": "shaper"
- },
- {
- "title": "Shepard",
- "category": "Role",
- "slug": "shepard"
- },
- {
- "slug": "story",
- "title": "Story"
- },
- {
- "slug": "supply",
- "title": "Supply"
- },
- {
- "title": "Terrain 2",
- "category": "Terrain",
- "slug": "terrain-2"
- },
- {
- "title": "Terrain 3",
- "category": "Terrain",
- "slug": "terrain-3"
- },
- {
- "slug": "terrain-cards",
- "title": "Terrain Cards"
- },
- {
- "title": "Terrain",
- "category": "Terrain",
- "slug": "terrain"
- },
- {
- "title": "Totem of the Irix",
- "category": "Gear",
- "slug": "totem-of-the-irix"
- },
- {
- "slug": "trade",
- "title": "Trade"
- },
- {
- "title": "Trader",
- "category": "Role",
- "slug": "trader"
- },
- {
- "slug": "trail-markers",
- "title": "Trail Markers"
- },
- {
- "slug": "travel-phase",
- "title": "Travel Phase"
- },
- {
- "slug": "traverse",
- "title": "Traverse"
- },
- {
- "slug": "unmaintained-roads",
- "title": "Unmaintained Roads"
- },
- {
- "slug": "valley",
- "title": "Valley"
- },
- {
- "slug": "victory-condition",
- "title": "Victory Condition"
- },
- {
- "title": "Wasteland 1",
- "category": "Region",
- "slug": "wasteland-1"
- },
- {
- "slug": "wasteland",
- "title": "Wasteland"
- },
- {
- "title": "Water 1",
- "category": "Region",
- "slug": "water-1"
- },
- {
- "title": "Water 2",
- "category": "Region",
- "slug": "water-2"
- },
- {
- "title": "Water 3",
- "category": "Region",
- "slug": "water-3"
- },
- {
- "title": "Water 4",
- "category": "Region",
- "slug": "water-4"
- },
- {
- "title": "Water 5",
- "category": "Region",
- "slug": "water-5"
- },
- {
- "slug": "weather",
- "title": "Weather"
- },
- {
- "slug": "white-sky",
- "title": "White Sky"
- },
- {
- "slug": "xp-cubes",
- "title": "XP Cubes"
- },
- {
- "slug": "xp",
- "title": "XP"
- }
- ]
-}
+{
+ "notes": [
+ {
+ "slug": "artificer",
+ "title": "Artificer",
+ "category": "Role"
+ },
+ {
+ "slug": "awareness",
+ "title": "Awareness"
+ },
+ {
+ "slug": "cache-map",
+ "title": "Cache Map",
+ "category": "Gear"
+ },
+ {
+ "slug": "card-library",
+ "title": "Card Library"
+ },
+ {
+ "slug": "concoliator",
+ "title": "Concoliator",
+ "category": "Role"
+ },
+ {
+ "slug": "contents",
+ "title": "Contents"
+ },
+ {
+ "slug": "crisis-markers",
+ "title": "Crisis Markers"
+ },
+ {
+ "slug": "crisis-resolution",
+ "title": "Crisis Resolution"
+ },
+ {
+ "slug": "crisis",
+ "title": "Crisis"
+ },
+ {
+ "slug": "dirt-roads",
+ "title": "Dirt Roads"
+ },
+ {
+ "slug": "dolewood-canoe",
+ "title": "Dolewood Canoe",
+ "category": "Gear"
+ },
+ {
+ "slug": "e03",
+ "title": "E.03",
+ "category": "Event"
+ },
+ {
+ "slug": "ecology",
+ "title": "Ecology"
+ },
+ {
+ "slug": "endeavor-tokens",
+ "title": "Endeavor Tokens"
+ },
+ {
+ "slug": "energy-tokens",
+ "title": "Energy Tokens"
+ },
+ {
+ "slug": "event-cards",
+ "title": "Event Cards"
+ },
+ {
+ "slug": "events",
+ "title": "Events"
+ },
+ {
+ "slug": "explore-phase",
+ "title": "Explore Phase"
+ },
+ {
+ "slug": "explorer",
+ "title": "Explorer",
+ "category": "Role"
+ },
+ {
+ "slug": "ferinodex",
+ "title": "Ferinodex",
+ "category": "Gear"
+ },
+ {
+ "slug": "flora-meeples",
+ "title": "Flora Meeples"
+ },
+ {
+ "slug": "forest-1",
+ "title": "Forest 1",
+ "category": "Region"
+ },
+ {
+ "slug": "forest-2",
+ "title": "Forest 2",
+ "category": "Region"
+ },
+ {
+ "slug": "forest-3",
+ "title": "Forest 3",
+ "category": "Region"
+ },
+ {
+ "slug": "forest-4",
+ "title": "Forest 4",
+ "category": "Region"
+ },
+ {
+ "slug": "forest-5",
+ "title": "Forest 5",
+ "category": "Region"
+ },
+ {
+ "slug": "forest",
+ "title": "Forest"
+ },
+ {
+ "slug": "gauzeblade",
+ "title": "Gauzeblade",
+ "category": "Gear"
+ },
+ {
+ "slug": "gear-cards",
+ "title": "Gear Cards"
+ },
+ {
+ "slug": "grass-1",
+ "title": "Grass 1",
+ "category": "Region"
+ },
+ {
+ "slug": "grass-2",
+ "title": "Grass 2",
+ "category": "Region"
+ },
+ {
+ "slug": "grass-3",
+ "title": "Grass 3",
+ "category": "Region"
+ },
+ {
+ "slug": "grass-4",
+ "title": "Grass 4",
+ "category": "Region"
+ },
+ {
+ "slug": "grass-5",
+ "title": "Grass 5",
+ "category": "Region"
+ },
+ {
+ "slug": "grasslands",
+ "title": "Grasslands"
+ },
+ {
+ "slug": "guide",
+ "title": "Guide",
+ "category": "Role"
+ },
+ {
+ "slug": "hidden-trail-map",
+ "title": "Hidden Trail Map",
+ "category": "Gear"
+ },
+ {
+ "slug": "injury-cards",
+ "title": "Injury Cards"
+ },
+ {
+ "slug": "lake",
+ "title": "Lake"
+ },
+ {
+ "slug": "losing-the-game",
+ "title": "Losing the Game"
+ },
+ {
+ "slug": "market",
+ "title": "Market"
+ },
+ {
+ "slug": "mountain-1",
+ "title": "Mountain 1",
+ "category": "Region"
+ },
+ {
+ "slug": "mountain-2",
+ "title": "Mountain 2",
+ "category": "Region"
+ },
+ {
+ "slug": "mountain-3",
+ "title": "Mountain 3",
+ "category": "Region"
+ },
+ {
+ "slug": "mountain-4",
+ "title": "Mountain 4",
+ "category": "Region"
+ },
+ {
+ "slug": "mountain-5",
+ "title": "Mountain 5",
+ "category": "Region"
+ },
+ {
+ "slug": "mountain",
+ "title": "Mountain"
+ },
+ {
+ "slug": "paratrepsis-whistle",
+ "title": "Paratrepsis Whistle",
+ "category": "Gear"
+ },
+ {
+ "slug": "paved-roads",
+ "title": "Paved Roads"
+ },
+ {
+ "slug": "perfect-day-1",
+ "title": "Perfect Day 1",
+ "category": "Event"
+ },
+ {
+ "slug": "phonoscopic-headset",
+ "title": "Phonoscopic Headset",
+ "category": "Gear"
+ },
+ {
+ "slug": "player-boards",
+ "title": "Player Boards"
+ },
+ {
+ "slug": "player-meeples",
+ "title": "Player Meeples"
+ },
+ {
+ "slug": "predator-meeples",
+ "title": "Predator Meeples"
+ },
+ {
+ "slug": "prepare-phase",
+ "title": "Prepare Phase"
+ },
+ {
+ "slug": "press-on",
+ "title": "Press On"
+ },
+ {
+ "slug": "prey-meeples",
+ "title": "Prey Meeples"
+ },
+ {
+ "slug": "progress",
+ "title": "Progress"
+ },
+ {
+ "slug": "ranger-badges",
+ "title": "Ranger Badges"
+ },
+ {
+ "slug": "ranger-meeples",
+ "title": "Ranger Meeples"
+ },
+ {
+ "slug": "research-station",
+ "title": "Research Station"
+ },
+ {
+ "slug": "rest",
+ "title": "Rest"
+ },
+ {
+ "slug": "role-cards",
+ "title": "Role Cards"
+ },
+ {
+ "slug": "round",
+ "title": "Round"
+ },
+ {
+ "slug": "ruins-map",
+ "title": "Ruins Map",
+ "category": "Gear"
+ },
+ {
+ "slug": "scout",
+ "title": "Scout"
+ },
+ {
+ "slug": "shaper",
+ "title": "Shaper",
+ "category": "Role"
+ },
+ {
+ "slug": "shepard",
+ "title": "Shepard",
+ "category": "Role"
+ },
+ {
+ "slug": "story",
+ "title": "Story"
+ },
+ {
+ "slug": "supply",
+ "title": "Supply"
+ },
+ {
+ "slug": "terrain-2",
+ "title": "Terrain 2",
+ "category": "Terrain"
+ },
+ {
+ "slug": "terrain-3",
+ "title": "Terrain 3",
+ "category": "Terrain"
+ },
+ {
+ "slug": "terrain-cards",
+ "title": "Terrain Cards"
+ },
+ {
+ "slug": "terrain",
+ "title": "Terrain",
+ "category": "Terrain"
+ },
+ {
+ "slug": "totem-of-the-irix",
+ "title": "Totem of the Irix",
+ "category": "Gear"
+ },
+ {
+ "slug": "trade",
+ "title": "Trade"
+ },
+ {
+ "slug": "trader",
+ "title": "Trader",
+ "category": "Role"
+ },
+ {
+ "slug": "trail-markers",
+ "title": "Trail Markers"
+ },
+ {
+ "slug": "travel-phase",
+ "title": "Travel Phase"
+ },
+ {
+ "slug": "traverse",
+ "title": "Traverse"
+ },
+ {
+ "slug": "unmaintained-roads",
+ "title": "Unmaintained Roads"
+ },
+ {
+ "slug": "valley",
+ "title": "Valley"
+ },
+ {
+ "slug": "victory-condition",
+ "title": "Victory Condition"
+ },
+ {
+ "slug": "wasteland-1",
+ "title": "Wasteland 1",
+ "category": "Region"
+ },
+ {
+ "slug": "wasteland",
+ "title": "Wasteland"
+ },
+ {
+ "slug": "water-1",
+ "title": "Water 1",
+ "category": "Region"
+ },
+ {
+ "slug": "water-2",
+ "title": "Water 2",
+ "category": "Region"
+ },
+ {
+ "slug": "water-3",
+ "title": "Water 3",
+ "category": "Region"
+ },
+ {
+ "slug": "water-4",
+ "title": "Water 4",
+ "category": "Region"
+ },
+ {
+ "slug": "water-5",
+ "title": "Water 5",
+ "category": "Region"
+ },
+ {
+ "slug": "weather",
+ "title": "Weather"
+ },
+ {
+ "slug": "white-sky",
+ "title": "White Sky"
+ },
+ {
+ "slug": "xp-cubes",
+ "title": "XP Cubes"
+ },
+ {
+ "slug": "xp",
+ "title": "XP"
+ }
+ ]
+}
\ No newline at end of file