From 166df1cff1bf04ed5e76ff7b071afd6c7065fc77 Mon Sep 17 00:00:00 2001 From: Sebin Nyshkim Date: Mon, 23 Jun 2025 18:52:18 +0200 Subject: [PATCH 01/12] fix: :bug: remove duplicate icon in set --- src/components/icon.webc | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/components/icon.webc b/src/components/icon.webc index 7eacfbe..e231730 100644 --- a/src/components/icon.webc +++ b/src/components/icon.webc @@ -154,18 +154,6 @@ /> - -
diff --git a/src/jarek/jarek.11tydata.js b/src/jarek/jarek.11tydata.js index 3c66826..283e330 100644 --- a/src/jarek/jarek.11tydata.js +++ b/src/jarek/jarek.11tydata.js @@ -42,11 +42,11 @@ const getWeight = () => `${weight} kg (${toLbs(weight)} lbs)`; const getTailLength = () => `${tailLength / 100} m (${toImperial(tailLength)})`; const getTraits = () => [ - // { icon: 'cake-candles', type: 'Date of Birth', text: getDateOfBirth() }, - { icon: 'mars', type: 'Sex/Gender', text: gender }, - { icon: 'ruler', type: 'Height', text: getHeight() }, - { icon: 'weight-hanging', type: 'Weight', text: getWeight() }, - { icon: 'ruler', type: 'Tail Length', text: getTailLength() } + // { icon: 'fa6-solid:cake-candles', type: 'Date of Birth', text: getDateOfBirth() }, + { icon: 'fa6-solid:mars', type: 'Sex/Gender', text: gender }, + { icon: 'fa6-solid:ruler', type: 'Height', text: getHeight() }, + { icon: 'fa6-solid:weight-hanging', type: 'Weight', text: getWeight() }, + { icon: 'fa6-solid:ruler', type: 'Tail Length', text: getTailLength() } ]; const getColors = () => [ diff --git a/src/sebin/sebin.11tydata.js b/src/sebin/sebin.11tydata.js index 69c787c..3095909 100644 --- a/src/sebin/sebin.11tydata.js +++ b/src/sebin/sebin.11tydata.js @@ -221,54 +221,54 @@ const getTraits = (type) => { switch (type) { case 'general': return [ - { icon: 'ruler', type: 'Tail Length', text: getTailLength() }, - { icon: 'shoe-prints', type: 'Walk', text: 'plantigrade' }, - { icon: 'info', type: 'Claws', text: 'sharp, hands & feet' }, - { icon: 'info', type: 'Nipples', text: 'yes' } + { icon: 'fa6-solid:ruler', type: 'Tail Length', text: getTailLength() }, + { icon: 'fa6-solid:shoe-prints', type: 'Walk', text: 'plantigrade' }, + { icon: 'fa6-solid:info', type: 'Claws', text: 'sharp, hands & feet' }, + { icon: 'fa6-solid:info', type: 'Nipples', text: 'yes' } ]; case 'wings': return [ - { icon: 'ruler', type: 'Wingspan', text: getWingspan() }, - { icon: 'feather', type: 'Arms', text: 2 }, - { icon: 'feather', type: 'Fingers', text: 3 }, - { icon: 'star', type: 'Special Features', text: 'talon on top' } + { icon: 'fa6-solid:ruler', type: 'Wingspan', text: getWingspan() }, + { icon: 'fa6-solid:feather', type: 'Arms', text: 2 }, + { icon: 'fa6-solid:feather', type: 'Fingers', text: 3 }, + { icon: 'fa6-solid:star', type: 'Special Features', text: 'talon on top' } ]; case 'head': return [ - { icon: 'eye', type: 'Pupils', text: 'round' }, - { icon: 'eye', type: 'Eyebrows', text: 'yellow spikes' }, - { icon: 'info', type: 'Cheeks', text: 'yellow spikes' }, - { icon: 'dragon', type: 'Horns', text: 'curved' }, - { icon: 'info', type: 'Hair', text: 'mid-long, mullet' }, - { icon: 'ear-listen', type: 'Ears', text: 'long, pointy, movable' }, - { icon: 'tooth', type: 'Teeth', text: 'sharp fangs' }, - { icon: 'face-grin-tongue', type: 'Tongue', text: 'pointy tip' } + { icon: 'fa6-solid:eye', type: 'Pupils', text: 'round' }, + { icon: 'fa6-solid:eye', type: 'Eyebrows', text: 'yellow spikes' }, + { icon: 'fa6-solid:info', type: 'Cheeks', text: 'yellow spikes' }, + { icon: 'fa6-solid:dragon', type: 'Horns', text: 'curved' }, + { icon: 'fa6-solid:info', type: 'Hair', text: 'mid-long, mullet' }, + { icon: 'fa6-solid:ear-listen', type: 'Ears', text: 'long, pointy, movable' }, + { icon: 'fa6-solid:tooth', type: 'Teeth', text: 'sharp fangs' }, + { icon: 'fa6-solid:face-grin-tongue', type: 'Tongue', text: 'pointy tip' } ]; case 'muscle': return [ - { icon: 'dumbbell', type: 'Build', text: 'muscular' }, - { icon: 'dumbbell', type: 'Pecs', text: 'big' }, - { icon: 'dumbbell', type: 'abs', text: 'defined' } + { icon: 'fa6-solid:dumbbell', type: 'Build', text: 'muscular' }, + { icon: 'fa6-solid:dumbbell', type: 'Pecs', text: 'big' }, + { icon: 'fa6-solid:dumbbell', type: 'abs', text: 'defined' } ]; case 'naughty': return [ - { icon: 'ruler', type: 'Length', text: `${penis.size} cm (${toInch(penis.size)})` }, - { icon: 'ruler', type: 'Girth', text: `${penis.girth} cm (${toInch(penis.girth)})` }, - { icon: 'shapes', type: 'Shape', text: penis.shape }, - { icon: 'maximize', type: 'Type', text: penis.type }, - { icon: 'star', type: 'Special Features', text: penis.special } + { icon: 'fa6-solid:ruler', type: 'Length', text: `${penis.size} cm (${toInch(penis.size)})` }, + { icon: 'fa6-solid:ruler', type: 'Girth', text: `${penis.girth} cm (${toInch(penis.girth)})` }, + { icon: 'fa6-solid:shapes', type: 'Shape', text: penis.shape }, + { icon: 'fa6-solid:maximize', type: 'Type', text: penis.type }, + { icon: 'fa6-solid:star', type: 'Special Features', text: penis.special } ]; default: return [ - { icon: 'cake-candles', type: 'Date of Birth', text: getDateOfBirth() }, - { icon: 'mars', type: 'Sex/Gender', text: `${gender} (${pronouns})` }, - { icon: 'ruler', type: 'Height', text: getHeight() }, - { icon: 'weight-hanging', type: 'Weight', text: getWeight() } + { icon: 'fa6-solid:cake-candles', type: 'Date of Birth', text: getDateOfBirth() }, + { icon: 'fa6-solid:mars', type: 'Sex/Gender', text: `${gender} (${pronouns})` }, + { icon: 'fa6-solid:ruler', type: 'Height', text: getHeight() }, + { icon: 'fa6-solid:weight-hanging', type: 'Weight', text: getWeight() } ]; } }; diff --git a/src/viktor/viktor.11tydata.js b/src/viktor/viktor.11tydata.js index bf9983e..a34c63f 100644 --- a/src/viktor/viktor.11tydata.js +++ b/src/viktor/viktor.11tydata.js @@ -22,37 +22,37 @@ const firstName = 'Viktor', jobs = [ { title: 'Bartender', - icon: 'whiskey', + icon: 'fa6-solid:whiskey-glass', desc: "Viktor's professional career began as a bartender at a pub in his hometown. There he often doubled as a bouncer when a few guests got too drunk and started making a fuss. A defining moment of that job was when someone climbed over the counter and threatened him with a broken bottle. Wrestled to the ground and with a broken bottle in front of his face, he had to make a split-second decision. With a powerful swing of his tail bone, he knocked the attacker down. This experience taught him the importance of effectively defending himself against unpleasant fellows and to eliminate threats before they get close to him ever again." }, { title: 'Lumberjack', - icon: 'tree', + icon: 'fa6-solid:tree', desc: 'After leaving his hometown, Viktor started working as a lumberjack. The club at the end of his tail came very much in handy as a counterweight for each swing of his axe, allowing him to strike efficiently and powerfully, felling even the largest trees with relative ease. His naturally tough scales protected him from splinters from the felled wood. The long-lasting hard physical work toughened his body over the years. Before taking the cut logs to the sawmill, Viktor always took a break to rest in the peace and quiet of the forest. Although he enjoyed the seclusion of the country life for a while, he was longing for the sociability of city life again.' }, { title: 'Car Mechanic', - icon: 'car', + icon: 'fa6-solid:car', desc: 'Moving into a suburban town, Viktor applied at an auto repair shop, where he learned the ins and outs of fixing cars. He became really good at it and enjoyed breathing new mechanical life into broken down vehicles. However, as time went on, the repair shop faced financial troubles, as it became increasingly difficult to come by spare parts as auto makers would only deal them to certified repair partners and certifications were prohibitively expensive. Viktor had to watch business slowly deteriorate, as skilled coworkers kept getting laid off, until the repair shop closed down for good.' }, { title: 'Construction Worker', - icon: 'helmet-safety', + icon: 'fa6-solid:helmet-safety', desc: 'Having taken a liking in physically demanding work, Viktor took on a job as a construction worker. Hard hat perched atop his head and belt tool slung around his waist, he was always ready to lend a hand (or tail if walls or boulders needed a good teardown). Since he had more than enough strength training from his previous jobs, he was often assigned carrying jobs to clear the site and haul building materials. After work was done, Viktor enjoyed the company of his colleagues over an after-work beer until late in the evenings. On one of these evenings, he got a little reckless with a colleague under the veil of the night and both were caught in the act of fooling around with each other on the construction site. In the following weeks, the colleagues kept their distance from Viktor and the evenings together also dissolved very quickly when he joined them. The continued ostracization ultimately prompted him to look for something new.' }, { title: 'Welder', - icon: 'industry', + icon: 'fa6-solid:industry', desc: 'In his job as a welder, Viktor spent his days working shifts in a workshop. In addition to special tools and plasma welders, he also used his powerful tail club to hammer metal parts into shape. He acquired a wide variety of welding techniques to join or repair metal structures. He worked with a wide variety of alloys such as steel, aluminum and titanium. Viktor showed extreme skill in his work with great precision and attention to detail. However, this dedication was a thorn in the side of a jealous colleague who saw Viktor as a rival and schemed against him, sabotaging his work, which ultimately ended in his termination after a customer sued the welding shop for botching the job. Viktor never found out who the culprit was, and the loss of that job still hangs over him.' }, { title: 'Delivery Driver', - icon: 'truck', + icon: 'fa6-solid:truck', desc: "When Viktor was strapped for cash, he took on a job in the gig economy as a driver delivering packages for a large online delivery service. His previous physically demanding jobs allowed him to haul even bulky deliveries to their destination with relative ease. If the shipping center managers hadn't been breathing down his neck constantly, he might have held this job even longer. But after one of the managers tried to show him up in front of the whole team, he snapped and broke their leg with his tail club. Of course, he didn't have to report for duty the next day." }, { title: 'Docks Werehouse Worker', - icon: 'boxes-stacked', + icon: 'fa6-solid:boxes-stacked', desc: "Currently Viktor works at the docks in the port town he moved to. His main responsibilities include loading and unloading cargo from ships and transporting it to and from warehousing. The hustle and bustle of the port sometimes gets on his nerves. Especially when the crew of docking ships come ashore again after a long time and make it clear that they don't have much contact with \"landlubbers\". Viktor doesn't get particularly impressed by this and foul mouths them right back if he gets the impression they're looking for trouble." } ]; @@ -118,16 +118,16 @@ const getTraits = (type) => { switch (type) { case 'naughty': return [ - { icon: 'heart', type: 'Orientation', text: orientation }, - { icon: 'arrows-up-down', type: 'Role', text: role } + { icon: 'fa6-solid:heart', type: 'Orientation', text: orientation }, + { icon: 'fa6-solid:arrows-up-down', type: 'Role', text: role } ]; default: return [ - { icon: 'cake-candles', type: 'Date of Birth', text: getDateOfBirth() }, - { icon: 'mars', type: 'Sex/Gender', text: `${gender} (${pronouns})` }, - { icon: 'ruler', type: 'Height', text: getHeight() }, - { icon: 'weight-hanging', type: 'Weight', text: getWeight() } + { icon: 'fa6-solid:cake-candles', type: 'Date of Birth', text: getDateOfBirth() }, + { icon: 'fa6-solid:mars', type: 'Sex/Gender', text: `${gender} (${pronouns})` }, + { icon: 'fa6-solid:ruler', type: 'Height', text: getHeight() }, + { icon: 'fa6-solid:weight-hanging', type: 'Weight', text: getWeight() } ]; } }; From 841c76c13ab7f242b8dfbd4f5f90ae8796ed5e5c Mon Sep 17 00:00:00 2001 From: Sebin Nyshkim Date: Mon, 23 Jun 2025 19:18:15 +0200 Subject: [PATCH 03/12] feat: :sparkles: add hobbies to sebin index page --- src/components/icon.webc | 48 +++++++++++++++++++++++++++++++++++++ src/sebin/index.md | 4 ++++ src/sebin/sebin.11tydata.js | 10 +++++++- 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/components/icon.webc b/src/components/icon.webc index 94b21af..da121e8 100644 --- a/src/components/icon.webc +++ b/src/components/icon.webc @@ -298,6 +298,54 @@ /> + + + + + + + + Here you would see an illustration… If I had one…
-

-

+

+
diff --git a/src/sebin/abilities.md b/src/sebin/abilities.md index 0d6748e..d6863cf 100644 --- a/src/sebin/abilities.md +++ b/src/sebin/abilities.md @@ -8,8 +8,18 @@ Since Sebin is a fire dragon there's a myriad of abilities he has at his disposa ## Attacks - + + Like most fire dragons, Sebin can breathe fire. In order to do this, he takes a deep breath to enrich the oxygen in his lungs with gases, which, together with special glands in his mouth, produce a combustible mixture. The resulting jet of fire, reaching several hundred degrees Celsius, spreads out on its way to its target, scorching everything in its path. + + + + By spitting fire into his hands, Sebin can form it into a ball and use it as a projectile. His scales are fireproof and can withstand the high temperatures. Due to their high concentration, the projectiles explode upon impact. By combining two fireballs the explosion radius increases dramatically. + + + + Apart from throwing projectiles, Sebin can also use the fireballs to wrap his fists in fire. This allows him to inflict severe burns on his opponent with each blow. In addition, he can release the fire from his fists with aimed blows and hurl it at his opponents. + + + + A technique used in aerial combat, Sebin uses his fire breath to engulf his body in flames while spinning to become a fire tornado that singes opponents. + diff --git a/src/sebin/overdrive.md b/src/sebin/overdrive.md index f02f1e8..5e23ec0 100644 --- a/src/sebin/overdrive.md +++ b/src/sebin/overdrive.md @@ -24,8 +24,34 @@ Direct body contact with Sebin during overdrive causes 3rd degree burns as he em ## Attacks - + + The reach of Sebin's Fire Breath increases as well as the frequency at which he can fire shots from his mouth. + + + + Overdrive Form eliminates the need for Sebin to spit fire into his palms. It instead enables him to fire the shots directly from the palm palm of his hands, as the firey veins crossing his arms act as an orifice to do so. The explosion radius of the burning projectiles that explode on impact is greatly increased. + + + + As his arms and legs are infused with fire his punches and kicks exert trails of flames while doing so. Landing a punch or kick sears enemies. + + + + Overdrive allows Sebin to form rings of fire by igniting flames from his fingertips and swirling them in a circle motion. He can use them for both close quarters or ranged combat. + + + + Clinking both of his wrists against each other like flints unleashes a devestating fire blast from both of his fire-infused hands. A secure foothold is needed to prevent Sebin from being thrown back by the recoil of the attack. Using this technique in the air is therefore highly risky. + + + + A heavy impact into the ground from a great height with both fists, tearing deep cracks in the ground around the impact crater. Combined with Kindled Fist the heat in Sebin's arms are forced through the newly created furrows, transforming the scene into an inferno. + + + + A fiery blade towering several meters into the air that Sebin sends careening towards his enemies from his fire-infused legs with a backflip kick, leaving a swath of destruction in its wake. Upon impact the force of the attack is distributed sideways. + + + + A rather defensive technique. By spinning around with stretched out arms Sebin creates fire balls, which he usually hurls towards enemies, that circle around his body diagonally. They act as a shield while he can still move his arms relatively freely. Enemies would be well advised to keep their distance to this spinning shield, as the fire balls will still explode on contact. + diff --git a/src/sebin/sebin.11tydata.js b/src/sebin/sebin.11tydata.js index 7c67767..1df822b 100644 --- a/src/sebin/sebin.11tydata.js +++ b/src/sebin/sebin.11tydata.js @@ -32,82 +32,6 @@ const firstName = 'Sebin', girth: 5 // cm }, description = 'Learn all about that derg!', - attacks = [ - { - id: 'attack-fire-breath', - name: 'Fire Breath', - description: - 'Like most fire dragons, Sebin can breathe fire. In order to do this, he takes a deep breath to enrich the oxygen in his lungs with gases, which, together with special glands in his mouth, produce a combustible mixture. The resulting jet of fire, reaching several hundred degrees Celsius, spreads out on its way to its target, scorching everything in its path.' - }, - { - id: 'attack-flame-toss', - name: 'Flame Toss', - description: - 'By spitting fire into his hands, Sebin can form it into a ball and use it as a projectile. His scales are fireproof and can withstand the high temperatures. Due to their high concentration, the projectiles explode upon impact. By combining two fireballs the explosion radius increases dramatically.' - }, - { - id: 'attack-kindled-fist', - name: 'Kindled Fist', - description: - 'Apart from throwing projectiles, Sebin can also use the fireballs to wrap his fists in fire. This allows him to inflict severe burns on his opponent with each blow. In addition, he can release the fire from his fists with aimed blows and hurl it at his opponents.' - }, - { - id: 'attack-burning-twister', - name: 'Burning Twister', - description: - 'A technique used in aerial combat, Sebin uses his fire breath to engulf his body in flames while spinning to become a fire tornado that singes opponents.' - } - ], - overdriveAttacks = [ - { - id: 'attack-fire-breath', - name: 'Fire Breath (improved)', - description: - "The reach of Sebin's Fire Breath increases as well as the frequency at which he can fire shots from his mouth." - }, - { - id: 'attack-flame-toss', - name: 'Flame Toss (improved)', - description: - 'Overdrive Form eliminates the need for Sebin to spit fire into his palms. It instead enables him to fire the shots directly from the palm palm of his hands, as the firey veins crossing his arms act as an orifice to do so. The explosion radius of the burning projectiles that explode on impact is greatly increased.' - }, - { - id: 'attack-kindled-fist', - name: 'Kindled Fist (improved)', - description: - 'As his arms and legs are infused with fire his punches and kicks exert trails of flames while doing so. Landing a punch or kick sears enemies.' - }, - { - id: 'attack-burning-twister', - name: 'Searing Discus', - description: - 'Overdrive allows Sebin to form rings of fire by igniting flames from his fingertips and swirling them in a circle motion. He can use them for both close quarters or ranged combat.' - }, - { - id: 'attack-fire-breath', - name: 'Combustion Flare', - description: - 'Clinking both of his wrists against each other like flints unleashes a devestating fire blast from both of his fire-infused hands. A secure foothold is needed to prevent Sebin from being thrown back by the recoil of the attack. Using this technique in the air is therefore highly risky.' - }, - { - id: 'attack-flame-toss', - name: 'Blazing Pandemonium', - description: - "A heavy impact into the ground from a great height with both fists, tearing deep cracks in the ground around the impact crater. Combined with Kindled Fist the heat in Sebin's arms are forced through the newly created furrows, transforming the scene into an inferno." - }, - { - id: 'attack-kindled-fist', - name: 'Scorching Edge', - description: - 'A fiery blade towering several meters into the air that Sebin sends careening towards his enemies from his fire-infused legs with a backflip kick, leaving a swath of destruction in its wake. Upon impact the force of the attack is distributed sideways.' - }, - { - id: 'attack-burning-twister', - name: 'Circling Fire Shield', - description: - 'A rather defensive technique. By spinning around with stretched out arms Sebin creates fire balls, which he usually hurls towards enemies, that circle around his body diagonally. They act as a shield while he can still move his arms relatively freely. Enemies would be well advised to keep their distance to this spinning shield, as the fire balls will still explode on contact.' - } - ], kinks = [ { name: 'Absorption', rating: 0 }, { name: 'Anal', rating: 3, receive: true, give: true }, @@ -299,8 +223,6 @@ export default { position, kinks, description, - attacks, - overdriveAttacks, getFullName, getTraits, getColors From db8cf3f93c8493e32d008fabaff464624785a8e6 Mon Sep 17 00:00:00 2001 From: Sebin Nyshkim Date: Thu, 26 Jun 2025 16:03:51 +0200 Subject: [PATCH 07/12] refactor: :recycle: use SVG sprite instead of individual SVGs This prevents 11ty with WebC/Markdown to produce excessive newlines in output markup --- src/components/icon-sprite.webc | 298 ++++++++++++++++++++++++ src/components/icon.webc | 388 +------------------------------- src/layouts/character.webc | 4 +- 3 files changed, 305 insertions(+), 385 deletions(-) create mode 100644 src/components/icon-sprite.webc diff --git a/src/components/icon-sprite.webc b/src/components/icon-sprite.webc new file mode 100644 index 0000000..00f2298 --- /dev/null +++ b/src/components/icon-sprite.webc @@ -0,0 +1,298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/icon.webc b/src/components/icon.webc index da121e8..ce119c8 100644 --- a/src/components/icon.webc +++ b/src/components/icon.webc @@ -1,389 +1,9 @@ -
-
-
- -
+
+
@@ -27,10 +25,8 @@ Hide NSFW -
-
- -
+
+
From 54882773a28c57f981c0f14734133e6944f3b2a9 Mon Sep 17 00:00:00 2001 From: Sebin Nyshkim Date: Thu, 26 Jun 2025 20:15:14 +0200 Subject: [PATCH 11/12] fix: :lipstick: border-radius affects svg icon --- src/components/timeline.webc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/timeline.webc b/src/components/timeline.webc index a576552..9f00e04 100644 --- a/src/components/timeline.webc +++ b/src/components/timeline.webc @@ -1,6 +1,6 @@
  • - +

  • @@ -19,7 +19,6 @@ @media (min-width: 32em) { --timeline-circle-size: 4rem; } - } :host .job { @@ -28,7 +27,6 @@ 'icon title' 'line text'; column-gap: 1em; - } :host .job::before { @@ -55,7 +53,7 @@ height: 50%; } - :host .icon { + :host .job > .icon { grid-area: icon; align-self: center; From 33e603cf05c4342458651c67c221193e33aaabe0 Mon Sep 17 00:00:00 2001 From: Sebin Nyshkim Date: Thu, 26 Jun 2025 20:23:47 +0200 Subject: [PATCH 12/12] docs: :memo: add README --- README.md | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..d286487 --- /dev/null +++ b/README.md @@ -0,0 +1,107 @@ +# Character Ref Pages + +Reference pages for all of the OCs (original characters) of [Sebin Nyshkim]. + +These reference pages are intended to provide artists with extensive info and reference material for commissions. + +## Technologies + +This project is built using [11ty] with [WebC]. It builds a (mostly) static website that's easy to serve with any webserver, no backend necessary. + +WebC allows for easily composable components that get compiled to standard HTML elements (with the option to have them compiled to native [web components]). + +For normal content pages, Markdown is used. Since Markdown allows the inclusion of HTML in `md` files, this is used to include WebC components in content pages. + +## Get up and running + +After cloning the repo, install the required NPM dependencies: + +```bash +npm install +``` + +11ty comes with an integrated web server with hot reloading for local development. To start it, simply: + +```bash +npm run start +``` + +> [!NOTE] +> There currently seems to be an issue with the way hot reloading and transformation works when using WebC and Markdown together in the same project. If the page doesn't update as expected after having made changes, restart the local dev server. + +To build the project, simply: + +```bash +npm run build +``` + +This puts the finished page into the `public` directory. All files can be deployed to a webserver as-is. + +## Project structure + +Per the `eleventy.config.js` file, all input files are located in the `src` directory. All other directories defined in the `config` object at the end of the config file are relative to the `src` directory. + +### Layouts + +Pages are mostly comprised of two layouts: `base` and `character`. The `base` layout provides the basic HTML structure with the `` and `` elements. The character pages all use the `character` layout. + +When adding a new character, make sure to add a corresponding directory data file with the same name as the character, i.e. `[character]/[character].11tydata.json` with the following content: + +```json +{ + "layout": "character.webc" +} +``` + +### Components + +WebC components in 11ty encapsulate HTML, CSS and JavaScript in a single file (similar to how Vue.js [SFCs] work). This greatly helps maintainability and separation of concerns. + +The modularized nature of WebC allows for a composable structure of 11ty websites, with their ability to use the `` element, which this project makes extensive use of. Together with special WebC extensions, like `webc:if` and `webc:for`, markup can be dynamically generated. Additionally, `