restructure correctly, add new features, start working on articles

This commit is contained in:
Rory Hinnen
2026-05-08 09:02:40 -05:00
parent 62c1303bbb
commit 82b40351f0
66 changed files with 311 additions and 106 deletions
+25
View File
@@ -0,0 +1,25 @@
import Ignite
struct Button: HTML {
private var name: String
private var link: String
let buttonWidth = 200
let buttonHeight = 70
init(name: String = "Hinnen", link: String = "Underground") {
self.name = name
self.link = link
}
var body: some HTML {
Link(name, target: link)
.linkStyle(.button)
.background(.blue)
.border(Color.black, width: 1)
.font(.custom("Futura", size: .em(1)))
.frame(width: buttonWidth, height: buttonHeight)
}
}
+53
View File
@@ -0,0 +1,53 @@
//
// LibraryBurroughs.swift
// IgniteStarter
//
// Created by Rory on 5/6/26.
//
import Ignite
struct LibraryBurroughs: HTML {
var body: some HTML {
Group {
Text("Edgar Rice Burrough: Barsoom and Amtor")
.font(.title2)
.horizontalAlignment(.center)
Text("""
Burroughs wrote these in the early part of the last century, and a they can be challenging to modern readers, both for the writing style and the content. They’re straightforward action, mostly focused on beating the bad guys and getting the girl (who always misunderstands our noble hero).
""")
HStack(alignment: .top ) {
VStack {
Text("The Barsoom Series")
.font(.title3)
List {
Link("A Princess of Mars", target: "/epubs/PrincessOfMars.epub")
Link("The Gods of Mars", target: "/epubs/GodsOfMars.epub")
Link("Warlord of Mars", target: "/epubs/WarlordOfMars.epub")
Link("Thuvia, Maid of Mars", target: "/epubs/ThuviaMaidOfMars.epub")
Link("Chessmen of Mars", target: "/epubs/ChessmenOfMars.epub")
Link("Fighting Man of Mars", target: "/epubs/FightingManOfMars.epub")
Link("Swords of Mars", target: "/epubs/SwordsOfMars.epub")
Link("Synthetic Men of Mars", target: "/epubs/SyntheticMenOfMars.epub")
Link("Llana of Gathol", target: "/epubs/LlanaOfGathol.epub")
Link("The Mastermind Of Mars", target: "/epubs/MastermindOfMars.epub")
Link("John Carter of Mars", target: "/epubs/JohnCarterOfMars.epub")
}
.horizontalAlignment(.leading)
}
VStack {
Text("The Amtor Series")
.font(.title3)
List {
Link("Pirates of Venus", target: "/epubs/PiratesOfVenus.epub")
Link("Lost on Venus", target: "/epubs/LostOnVenus.epub")
Link("Carson of Venus", target: "/epubs/CarsonOfVenus.epub")
Link("Escape on Venus", target: "/epubs/EscapeOnVenus.epub")
Link("The Wizard of Venus", target: "/epubs/WizardOfVenus.epub")
}
.horizontalAlignment(.leading)
}
}
.horizontalAlignment(.center)
}
}
}
+30
View File
@@ -0,0 +1,30 @@
//
// LibraryBurroughs.swift
// IgniteStarter
//
// Created by Rory on 5/6/26.
//
import Ignite
struct LibraryChandler: HTML {
var body: some HTML {
Group {
Text("Raymond Chandler")
.font(.title2)
.horizontalAlignment(.center)
Text("""
This man writes like an angel. And tells sordid stories of sin and debauchery.
""").horizontalAlignment(.leading)
VStack{
List {
Link("The Big Sleep", target: "/epubs/tbs.epub")
Link("The Little Sister", target: "/epubs/tls.epub")
}
.horizontalAlignment(.leading)
}
.horizontalAlignment(.center)
}
}
}
+29
View File
@@ -0,0 +1,29 @@
//
// LibraryBurroughs.swift
// IgniteStarter
//
// Created by Rory on 5/6/26.
//
import Ignite
struct LibraryGraham: HTML {
var body: some HTML {
Group {
Text("Kenneth Graham")
.font(.title2)
.horizontalAlignment(.center)
Text("""
Shoegaze. Soak in the psychodelia.
""").horizontalAlignment(.leading)
VStack{
List {
Link("The Wind in the Willows", target: "/epubs/twit.epub")
}
.horizontalAlignment(.leading)
}
.horizontalAlignment(.center)
}
}
}
+28
View File
@@ -0,0 +1,28 @@
//
// LibraryBurroughs.swift
// IgniteStarter
//
// Created by Rory on 5/6/26.
//
import Ignite
struct LibraryGray: HTML {
var body: some HTML { Group {
Text("Zane Gray")
.font(.title2)
.horizontalAlignment(.center)
Text("""
I am not a fan of the genre 'Western'. My dad is.
""").horizontalAlignment(.leading)
VStack{
List {
Link("The Mysterious Rider", target: "/epubs/mr.epub")
}
.horizontalAlignment(.leading)
}
.horizontalAlignment(.center)
}
}
}
+33
View File
@@ -0,0 +1,33 @@
//
// LibraryBurroughs.swift
// IgniteStarter
//
// Created by Rory on 5/6/26.
//
import Ignite
struct LibraryLovecraft: HTML {
var body: some HTML {
Group {
Text("Howard Phillips Lovecraft")
.font(.title2)
.horizontalAlignment(.center)
Text("""
Lovecraft has a cult following, which is funny because he always wrote about cults. He takes a view of a universe in which humanity is not only insignificant, but stands on the edge of doom once beings greater than we take notice.
""")
VStack{
List {
Link("At the Mountains of Madness", target: "/epubs/AtTheMountainsOfMadnes.epub")
Link("Dagon", target: "/epubs/dagon.epub")
Link("The Shadow Over Innsmouth", target: "/epubs/TheShadowOverInnsmouth.epub")
Link("Call of Cthulhu", target: "/epubs/CallOfCthulhu.epub")
Link("The Innsmouth Look", target: "/epubs/TheInnsmouthLook.epub")
}
.horizontalAlignment(.leading)
Emphasis("(All three in one!)")
}
.horizontalAlignment(.center)
}
}
}
+29
View File
@@ -0,0 +1,29 @@
//
// LibraryBurroughs.swift
// IgniteStarter
//
// Created by Rory on 5/6/26.
//
import Ignite
struct LibrarySmith: HTML {
var body: some HTML {
Group {
Text("E.E. \"Doc\" Smith")
.font(.title2)
.horizontalAlignment(.center)
Text("""
Just happy adventure stories with strong, exceptional men doing strong, exceptional things. Lensmen became a sort of model for Green Lantern, with its interstellar police who is above the law. I'm not going to defend these as great writing. I'm not going to defend these at all. It's just very juvenile fun.
""")
VStack{
List {
Link("Triplanetary", target: "/epubs/triplanetary.epub")
Link("First Lensman", target: "/epubs/flen.epub")
}
.horizontalAlignment(.leading)
}
.horizontalAlignment(.center)
}
}
}
+30
View File
@@ -0,0 +1,30 @@
//
// LibraryBurroughs.swift
// IgniteStarter
//
// Created by Rory on 5/6/26.
//
import Ignite
struct LibraryWells: HTML {
var body: some HTML {
Group {
Text("H.G. Wells")
.font(.title2)
.horizontalAlignment(.center)
Text("""
Wells is the Patron Saint of English Science Fiction. Verne might have been first, but Wells is the man who made it work. His books aren't always what you think. While he was an avid wargamer (he created what we consider one of the first tabletop wargames), he was a pacifist. War of the Worlds was a critique of British Empire building.
""")
VStack{
List {
Link("The War of the Worlds", target: "/epubs/twotw.epub")
Link("Little Wars", target: "/epubs/LittleWars.epub")
}
.horizontalAlignment(.leading)
}
.horizontalAlignment(.center)
}
}
}
+54
View File
@@ -0,0 +1,54 @@
import Ignite
struct Logo: HTML {
private var barTitle: String
private var underTitle: String
init(barTitle: String = "Hinnen", underTitle: String = "Underground") {
self.barTitle = barTitle
self.underTitle = underTitle
}
var body: some HTML {
// ── Logo ──────────────────────────────────────────────────────────────
// Simplified Underground logo using ZStack and SwiftUI-like modifiers
VStack {
ZStack {
// Red circle
Text("")
.frame(width: 190, height: 190)
.background(.red)
.cornerRadius(95)
.border(.black, width: 1)
// White circle
Text("")
.frame(width: 110, height: 110)
.background(.white)
.cornerRadius(55)
.border(.black, width: 1)
// Blue bar with "Hinnen"
VStack {
Spacer()
Text(barTitle.uppercased())
.foregroundStyle(.white)
.font(.custom("Futura", size: 33))
Spacer()
}
.frame(width: 214, height: 40, alignment: .center)
.background(.blue)
.border(.black, width: 1)
.horizontalAlignment(.center)
}
// "Underground" label beneath
Text(underTitle.uppercased())
.font(.custom("Futura", size: 25))
.frame(width: 214, alignment: .top)
.horizontalAlignment(.center)
}
.frame(width: 214)
}
}
+24
View File
@@ -0,0 +1,24 @@
//
// Mastodon.swift
// IgniteStarter
//
// Created by Rory on 5/5/26.
//
import Ignite
struct Mastodon: HTML {
var body: some HTML {
// ── Mastodon / rel=me links (hidden, for verification) ────────────────
Link("", target: "https://twit.social/@roryh")
.relationship(.me)
.hidden(.responsive(true))
Link("", target: "https://mograph.social/@Roryhinnen")
.relationship(.me)
.hidden(.responsive(true))
Link("", target: "https://cinematheque.social/@Rory")
.relationship(.me)
.hidden(.responsive(true))
}
}
+43
View File
@@ -0,0 +1,43 @@
//
// NavBar.swift
// IgniteSamples
// https://www.github.com/twostraws/Ignite
// See LICENSE for license information.
//
import Foundation
import Ignite
/// Displays a global "Social Footer", with each social icon linking to an
/// external site in a new browser tab, demonstrating how to create reusable
/// components with builtIn icons, external links and custom attributes.
struct SocialFooter: HTML {
let icons = [
Image(systemName: "github"),
Image(systemName: "twitter"),
Image(systemName: "youtube"),
Image(systemName: "mastodon")
]
let urlStrings = [
"https://github.com/twostraws",
"https://twitter.com/twostraws",
"https://youtube.com/@twostraws",
"https://mastodon.social/@twostraws"
]
var body: some HTML {
VStack {
HStack {
ForEach(zip(icons, urlStrings)) { (icon, urlString) in
Link(icon, target: urlString)
.role(.secondary)
.target(.blank)
.relationship(.noOpener, .noReferrer)
}
}
}
.margin(.top, .xLarge)
.font(.title2)
}
}
+18
View File
@@ -0,0 +1,18 @@
//
// Version Info.swift
// IgniteSamples
// https://www.github.com/twostraws/Ignite
// See LICENSE for license information.
//
import Ignite
/// Displays the version of Ignite the site was built with and the publishing date.
struct VersionInfo: HTML {
private let dateFormat = Date.FormatStyle().month(.defaultDigits).day(.defaultDigits).year(.twoDigits)
var body: some HTML {
Text("\(Ignite.version) · Updated \(Date.now.formatted(dateFormat))")
.horizontalAlignment(.center)
.foregroundStyle(.gray)
}
}
+10
View File
@@ -0,0 +1,10 @@
import Ignite
struct MainLayout: Layout {
var body: some Document {
Body {
content
IgniteFooter()
}
}
}
+17
View File
@@ -0,0 +1,17 @@
import Ignite
struct Adventures: StaticPage {
var path = "/adventures"
let title: String
init() {
self.title = "Adventures in Modern Coding"
}
var body: some HTML {
VStack {
Logo(barTitle: "Adventures".uppercased(), underTitle: "in Modern Coding".uppercased())
.horizontalAlignment(.center)
}
}
}
+24
View File
@@ -0,0 +1,24 @@
import Ignite
struct Battlefleet: StaticPage {
var path = "/battlefleet"
let title: String
init() {
self.title = "Battlefleet: Subsector Scarus"
}
var body: some HTML {
VStack {
Logo(barTitle: String(title.split(separator: " ").first ?? ""), underTitle: "Subector Scarus")
.horizontalAlignment(.center)
Link("Battlefleet Gothic Remastered Digital Rules", target: "/epubs/BattlefleetGothicDigitalRemaster.epub")
Link("Rebels List", target: "rebels.html")
Link("About Subsector Scarus", target: "about.html")
Text("Battlefleet Obscuras: Sector Scarus")
Text("Chaos Raiders: Thousand Sons")
Text("Archeo Xenos: Necrons")
Text("Commonwealth: T'au")
}
}
}
+31
View File
@@ -0,0 +1,31 @@
import Ignite
struct Index: StaticPage {
var title = "Hinnen Underground"
let buttonWidth = 200
let buttonHeight = 70
var body: some HTML {
VStack{
Logo()
.horizontalAlignment(.center)
Grid(alignment: .center, spacing: 4) {
Button(name: "Rory", link: "https://rory.hinnen.us")
Button(name: "Robin", link: "https://robin.hinnen.us")
Button(name: "Robin's Cancer Blog", link: "https://bab.hinnen.us")
Button(name: "MGA", link: "/mga/")
Button(name: "The Bel Aire Backyard Theatre", link: "/baby/")
Button(name: "Minecraft", link: "https://trenzelore.hinnen.us")
Button(name: "Legends of Dying Mars", link: "/barsoom/")
Button(name: "X-Wing Rules", link: "/X-Wing Reference.html")
Button(name: "Adventures in Modern Coding", link: "https://dev.hinnen.us")
Button(name: "The Library", link: "/library/")
Button(name: "Archeological remains", link: "https://nostalgicpinata.hinnen.us/")
Button(name: "Battlefleet: Sector Scarus", link: "/battlefleet/")
}
Mastodon()
}
.horizontalAlignment(.center)
}
}
+24
View File
@@ -0,0 +1,24 @@
import Ignite
struct Legends: StaticPage {
var path = "/barsoom"
let title: String
init() {
self.title = "Legends of Dying Mars"
}
var body: some HTML {
VStack {
Logo(barTitle: "Legends".uppercased(), underTitle: "of Dying Mars".uppercased())
.horizontalAlignment(.center)
Text(markdown: """
I have a couple of sets of rules that I've worked on, off and on, for small skirmishes on Barsoom.
My website is in the process of being rebuilt right now, so consider this a vintage _Under Construction_ sign.
I will try to get these rules republished under new management soon.
""")
}
}
}
+27
View File
@@ -0,0 +1,27 @@
import Ignite
struct Library: StaticPage {
var path = "/library"
let title: String
init() {
self.title = "The Library"
}
var body: some HTML {
VStack {
Logo(barTitle: title, underTitle: "")
.horizontalAlignment(.center)
Text("""
I love reading, but I really don’t get enough time to do that anymore. I've become enamoured of the the process of creating e-books. There's something about it that I very much enjoy.
""")
LibraryBurroughs()
LibraryLovecraft()
LibrarySmith()
LibraryGraham()
LibraryWells()
LibraryChandler()
LibraryGray()
}
}
}
+26
View File
@@ -0,0 +1,26 @@
import Ignite
struct MGA: StaticPage {
var path = "/mga"
let title: String
init() {
self.title = "MGA"
}
var body: some HTML {
VStack {
Logo(barTitle: title, underTitle: "")
.horizontalAlignment(.center)
Text(markdown: """
I have long wanted to restore a car. After an extensive round of research I decided that the car with the best support, cheapest parts and most available information was the MGB.
Of course, I ended up with an MGA.
While my site is busy being rebuilt, you'll have to console yourself with just that little story, but I will collect photos of my restoration and put them back up on the site.
Patience, padwan.
""")
}
}
}
+155
View File
@@ -0,0 +1,155 @@
import Ignite
struct Rebels: StaticPage {
var path = "/battlefleet/rebels.html"
let title: String
init() {
self.title = "Rebel Fleet list"
}
var body: some HTML {
VStack {
Text("Rebel Fleet List")
.font(.title1)
Text("By the two Rorys")
.font(.xSmall)
Text("Rory Grant and Rory Hinnen")
Divider()
Text(markdown: """
---
Loyalty in the Imperium can sometimes be a commodity. For every sector that obediently sends its tithe to Holy Terra, there is another that ponders the question, “What’s in it for me?”
And every so often, disobedience blossoms into full fledged insurrection and piracy. After all, if everyone respected the Emperor, there would be no need for the Inquisition.
Sometimes, a Prince will decide it’s time to elevate himself. Or a Governor’s allegiance is no longer to the Imperium, but to himself. Naval officers of a sector will suddenly support their new masters or find themselves orbiting a planet without the benefit of a ship. The resulting fleet will be a motley collection of current ships of the line, auxiliaries, and anything that can be pressed into service from a once loyal sector.
Alliances will be made with less than savory characters. Ships will be pulled out of reserves, cleaned up and pressed gainfully into service. The biggest and best ships will be hard to come by, and will be closely guarded by the new government.
---
The Rebel fleet rules attempts to model what this fleet will look like and play on the board. Large ships are hard to come by. Older ships are brought out of mothballs, cleaned of any chaotic taint, and pressed into service. A certain air of desperation clings to the whole enterprise. Playing a rebel list offers the opportunity of pulling ships from the history of the Imperium, but provides unique challenges of maintaining allied relationships and keeping your own people in line.
---
# **Special Rules**
## **Stalking Horse**
Allied ships that are part of the fleet don’t have the same level of enthusiasm for the conflict as the rebels. If the Allied ship is crippled (taken half its points in damage) or the overall fleet has lost half its ships, it will begin to consider its options.
Every turn the ship is crippled, or the rebel fleet is at half of its point value or less, roll for leadership. If the roll succeeds, the allies will decide that the battle is no longer in their interest; they will either flee or attack.
Roll on the following table:
1-5: Flee the field - Discretion is the better part of valor, the ship will disengage by the most expedient means available.
6: Attack former comrades - The alliance has collapsed in a flurry of anger and recriminations. The ship will turn on its former allies. The allied ship is now under the control of the opposing player.
## **Paint isn’t Structural**
Don’t feel obligated to maintain a coherent livery with a Rebel fleet. Rebels are not proud about where their ships come from, and are willing to take cast offs, hand-me-downs, or even, shall we say, less than legitimate channels of acquisition. The Arch-magos may complain, but sometimes we have to deploy a ship before all the appropriate consecration of paint has been applied.
---
# **Leadership**
## **Rebel Leader**
You may include one Rebel Leader in your fleet, who must be assigned to the most expensive ship or squadron. If the fleet is worth 500 points or more it must include at least 1 Rebel Leader. Rebel Leaders spend a lot of time keeping their coalition together, and start with -2 leadership.
Rebel Leader +10 pts
The leader gets one re-roll. They can have more re-rolls for the additional cost noted below.
One extra re-roll +20 pts
Two extra re-rolls +40 pts
The vessel carrying the Leader has his personal protective force on board, and gets a +1 against hostile boarding actions. By the same token, it gets a -1 on boarding actions from the rebel ship.
---
# **Ships**
## **0-1 Battleship, Grand Cruiser, Battlecruiser or Heavy Cruiser**
A fleet may include a single Battleship, Grand or Heavy Cruiser from either the Imperial or Chaos list. You may include this ship if you have at least 3 regular cruisers in the fleet.
This ship pulls leadership from the Rebel list.
## **O-1 Allied Ship**
Rebels may make an alliance with a non-Imperial representative. You may include this ship if you have at least 3 regular cruisers in the fleet. The non-Imperial factions are:
* Eldar
* Tau
* Rogue Trader
* Chaos
* Ork Cyclops Cluster Fleet
The Allied ship may not use any of the fleet re-rolls. They are not restricted to nor benefit from the leadership values of the rebel fleet and must use the unmodified leadership from the fleet lists of their respective races.
This ship is under different command from the rest of the fleet, being allied. Because of that, this ship may take any marks or advantages that are typical of that race, and leadership is rolled as that race. Fleet rerolls may not be applied to this ship, and if this ship has rerolls it may not use them for other ships in the fleet.
This ship may not squadron with other ships of the fleet.
This ship is subject to the *Stalking Horse* rules
## **0-12 Cruisers**
Tyrant Class Cruiser 185
Gothic Class Cruiser 180
Lunar Class Cruiser 180
Carnage Class Cruiser 180
Inferno Class Cruiser 180
Murder Class Cruiser 170
Slaughter Class Cruiser 165
Strike Cruiser 145
Endeavour Class Light Cruiser 110
Endurance Class Light Cruiser 110
Siluria Class Light Cruiser 100
Dauntless Class Light Cruiser 110
## **Escorts**
At least half your fleet (in points) needs to be composed of escorts. You may include any number of escorts in your fleet in squadrons of 2-6. Ships should be squadroned by type, unless there are no others of that type, and then it may be squadroned with another.
Idolator class raider 45
Infidel class raider 40
Gladius class frigate 45
Firestorm class frigate 40
Sword class frigate 35
Havoc class frigate 35
Falchion class frigate 35
Hunter class destroyer 40
Cobra class destroyer 30
Iconoclast destroyer 30
Viper class destroyer 35
## **Ordinance**
Any ship with launch bays may choose to have them launch any mix of Fury interceptors and Starhawk bombers. Some ships may carry Shark assault boats at an additional cost. Ships with torpedo tubes are armed with ordinary torpedoes.
---
# **Campaign Rules**
For campaigns, Rebel players are very similar to Imperial players.
Start with a sector. They can take advantage of Refits or Other as an appeal, but Reinforcements are limited to reflect their inability to call upon Imperial resources. Reinforcements are granted on a roll of 6. This represents the difficulty of producing or finding a replacement without the vast resources of the Empire of Man.
## **Eat the Rich**
Rebel players have a campaign option to capture an enemy ship and add it to their roster.
In order to capture a ship, the Rebel ship must initiate what is essentially a specialized boarding action. The damage done by a boarding party is considered to be disabling a system rather than actually destroying it.
The Rebel player must declare that the attack is to disable rather than destroy. Systems that are disabled must be tracked differently than systems that are destroyed in a normal boarding action.
Disabled systems can be rerouted/repaired faster than normal damage. During the damage control phase, the player of a ship with disabled points is able to repair the ship with a d6 roll of 4+.
If a ship is reduced to 0 points, but has at least one disabled point, it is considered captured. The owning player may fire upon a captured ship. Any damage made on a captured ship will convert a disabled point to a destroyed point.
If a captured ship manages to leave the board or survive a conflict, it will be added to the Rebel’s player roster after it is repaired. The Rebel player must expend points to repair the ship, but only damage points. So if a ship has 5 points of damage and 3 points of disabled, only 5 points need to be repaired.
""")
}
}
}
+25
View File
@@ -0,0 +1,25 @@
import Ignite
struct ScarusAbout: StaticPage {
var path = "/battlefleet/about.html"
let title: String
init() {
self.title = "Subsector Scarus"
}
var body: some HTML {
VStack {
Text("Subsector Scarus")
.font(.title1)
Divider()
Text(markdown: """
Subsector Scarus is to the north of Segmentum Terra, in the north east corner of Segmentum Obscurus.
This is the imaginary center of my _Battlefleet: Gothic_ fleets.
In a moment of gamer optimization, this Sector is well represented by the various factions of the 40th Millenia. T'au, Necrons, Imperial and Chaos are all found in various states of conflict here.
""")
}
}
}
+30
View File
@@ -0,0 +1,30 @@
import Ignite
struct Theatre: StaticPage {
var path = "/baby"
let title: String
init() {
self.title = "Bel Aire Backyard Theatre"
}
var body: some HTML {
VStack {
Logo(barTitle: "Bel Aire", underTitle: "Backyard Theatre")
.horizontalAlignment(.center)
Text(markdown: """
I *love* movies.
From my very first experiences in a theatre, to hot summer nights at the drive-in, I have always been in love with movies.
When our children were of "a certain age" we found it difficult to get out to see movies, so we decided to bring movies to our back yard.
It was a very good decision.
As my site is being rebuilt, you'll have to satisfy yourself with just that story. When I finish up, you'll find my adventures with backyard theatrics here.
*Soon.*
""")
}
}
}
+43
View File
@@ -0,0 +1,43 @@
import Ignite
@main
struct IgniteWebsite {
static func main() async {
var site = Hinnen()
do {
try await site.publish()
} catch {
print(error.localizedDescription)
}
}
}
struct Hinnen: Site {
var name = "Hinnen Underground"
var titleSuffix = ""
var url = URL(static: "https://www.hinnen.us")
var builtInIconsEnabled = true
var author = "Rory Hinnen"
var homePage = Index()
var layout = MainLayout()
var lightTheme: (any Theme)? = LightTheme()
var darkTheme: (any Theme)? = DarkTheme()
var favicon: URL? { URL(static: "/favicon/favicon.ico") }
var staticPages: [any StaticPage] {
Battlefleet()
Library()
Adventures()
Legends()
MGA()
Theatre()
Rebels()
ScarusAbout()
}
}
+64
View File
@@ -0,0 +1,64 @@
//
// Themes.swift
// IgniteStarter
//
// Created by Rory on 5/5/26.
//
import Ignite
protocol BaseTheme: Theme {}
// Default implementation for shared values
extension BaseTheme {
var siteWidth: ResponsiveValues { .init(small: .px(770)) }
// Prefer Avenir Next for the core font
var font: Font { .init(name: "Futura, system-ui, -apple-system, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, Liberation Sans, sans-serif", weight: .regular) }
// Prefer Menlo for monospaced font (code blocks)
var monospaceFont: Font { .init(name: "Menlo, SFMono-Regular, Monaco, Consolas, Liberation Mono, Courier New, monospace", weight: .regular) }
var codeBlockFontSize: LengthUnit { .px(16) }
var inlineCodeFontSize: LengthUnit { .px(16) }
var h1Size: ResponsiveValues { .init(LengthUnit.px(32)) } // 1.78x
var h2Size: ResponsiveValues { .init(LengthUnit.px(28)) } // 1.56x
var h3Size: ResponsiveValues { .init(LengthUnit.px(22)) } // 1.22x
var h4Size: ResponsiveValues { .init(LengthUnit.px(20)) } // 1.11x
var h5Size: ResponsiveValues { .init(LengthUnit.px(18)) } // Same as body
var h6Size: ResponsiveValues { .init(LengthUnit.px(16)) } // 0.89x body
var bodyFontSize: ResponsiveValues { .init(LengthUnit.px(18)) }
var lineSpacing: LengthUnit { .em(1.5) }
var headingLineSpacing: LengthUnit { .em(2) }
}
// Values not set here default to stock light theme colors
struct LightTheme: BaseTheme {
var colorScheme: ColorScheme = .light
var accent: Color { Color(hex: "#6366f1") } // blue ribbon
var secondaryAccent: Color { Color(hex: "#6366f1") } // blue ribbon
var secondary: Color { Color(hex: "#6b7280") } // pale sky
var secondaryBackground: Color { Color(hex: "#f8fafc") } // alabaster
var link: Color { Color(hex: "#6366f1") } // blue ribbon
var hoveredLink: Color { Color(hex: "#4f46e5") } // purple heart
var syntaxHighlighterTheme: HighlighterTheme { .solarizedLight }
}
// Values not set here default to stock dark theme colors
struct DarkTheme: BaseTheme {
var colorScheme: ColorScheme = .dark
var accent: Color { Color(hex: "#7dd3fc") } // malibu blue
var secondaryAccent: Color { Color(hex: "#e2e8f0") } // mystic gray
var secondary: Color { Color(hex: "#9ca3af") } // gray chateau
var background: Color { Color(hex: "#1e293b") } // ebony clay
var secondaryBackground: Color { Color(hex: "#334155") } // pickled bluewood
var link: Color { Color(hex: "#7dd3fc") } // malibu
var hoveredLink: Color { Color(hex: "#38bdf8") } // picton blue
var syntaxHighlighterTheme: HighlighterTheme { .githubDark }
}