Skip to content

Commit 0c45ea0

Browse files
committed
DND: From Serfs and Frauds 3
1 parent 9b9f7d5 commit 0c45ea0

File tree

17 files changed

+752
-47
lines changed

17 files changed

+752
-47
lines changed

public/dnd/episode1.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Episode 1: The Whispering Woods
2+
3+
Our heroes begin their journey in the quiet village of Oakhaven, nestled at the edge of the ancient Whispering Woods. Rumors of strange occurrences and disappearing travelers have reached the ears of the local elder, who implores the adventurers to investigate.
4+
5+
As they venture into the woods, the air grows heavy with an unnatural silence. The trees seem to watch them, their branches swaying in a breeze that carries no sound. A faint, ethereal glow emanates from deeper within the forest...

public/dnd/episode2.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Episode 2: The Goblin Ambush
2+
3+
Deeper within the Whispering Woods, our heroes stumble upon a crude goblin encampment. A band of goblins, led by a particularly nasty hobgoblin, are preparing an ambush for unsuspecting travelers.
4+
5+
A tense battle ensues, with arrows flying and crude blades clashing. The adventurers must use their wits and skills to overcome the goblin horde and rescue any captives they might find...

public/dnd/episodes.json

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
[
2+
{
3+
"bookId": 1,
4+
"bookTitle": "Book One: The Shadowed Path",
5+
"episodes": [
6+
{ "id": 1, "filename": "episode1.txt", "title": "Episode 1: The Whispering Woods", "author": "fezcode" },
7+
{ "id": 2, "filename": "episode2.txt", "title": "Episode 2: The Goblin Ambush", "author": "fezcode" }
8+
]
9+
},
10+
11+
{
12+
"bookId": 2,
13+
"bookTitle": "Book Two: Separated Bitches",
14+
"episodes": [
15+
{ "id": 1, "filename": "episode1.txt", "title": "Episode 1: The Whispering Woods", "author": "fezcode" },
16+
{ "id": 2, "filename": "episode2.txt", "title": "Episode 2: The Goblin Ambush", "author": "fezcode" }
17+
]
18+
},
19+
20+
{
21+
"bookId": 3,
22+
"bookTitle": "Book Three: Separated Bitches",
23+
"episodes": [
24+
{ "id": 1, "filename": "episode1.txt", "title": "Episode 1: The Whispering Woods", "author": "fezcode" },
25+
{ "id": 2, "filename": "episode2.txt", "title": "Episode 2: The Goblin Ambush", "author": "fezcode" }
26+
]
27+
},
28+
29+
{
30+
"bookId": 4,
31+
"bookTitle": "Book Four: Separated Bitches",
32+
"episodes": [
33+
{ "id": 1, "filename": "episode1.txt", "title": "Episode 1: The Whispering Woods", "author": "fezcode" },
34+
{ "id": 2, "filename": "episode2.txt", "title": "Episode 2: The Goblin Ambush", "author": "fezcode" }
35+
]
36+
}
37+
]

public/images/dnd/book-cover.png

1.2 MB
Loading

public/images/dnd/border-large.jpg

301 KB
Loading

public/images/dnd/parchment.png

-605 KB
Loading

src/components/AnimatedRoutes.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ import NotFoundPage from '../pages/NotFoundPage';
1313
import SeriesPage from '../pages/SeriesPage';
1414
import DndPage from '../pages/DndPage';
1515
import DndNotFoundPage from '../pages/DndNotFoundPage'; // New import
16+
import DndEpisodePage from '../pages/DndEpisodePage'; // New import
17+
import DndLorePage from '../pages/DndLorePage'; // New import
18+
import DndBookPage from '../pages/DndBookPage'; // New import
1619

1720
const pageVariants = {
1821
initial: {
@@ -206,6 +209,51 @@ function AnimatedRoutes() {
206209
</motion.div>
207210
}
208211
/>
212+
{/* D&D Lore Page */}
213+
<Route
214+
path="/dnd/lore"
215+
element={
216+
<motion.div
217+
initial="initial"
218+
animate="in"
219+
exit="out"
220+
variants={pageVariants}
221+
transition={pageTransition}
222+
>
223+
<DndLorePage />
224+
</motion.div>
225+
}
226+
/>
227+
{/* D&D Book Page */}
228+
<Route
229+
path="/dnd/books/:bookId"
230+
element={
231+
<motion.div
232+
initial="initial"
233+
animate="in"
234+
exit="out"
235+
variants={pageVariants}
236+
transition={pageTransition}
237+
>
238+
<DndBookPage />
239+
</motion.div>
240+
}
241+
/>
242+
{/* D&D Episode Page */}
243+
<Route
244+
path="/dnd/books/:bookId/pages/:episodeId"
245+
element={
246+
<motion.div
247+
initial="initial"
248+
animate="in"
249+
exit="out"
250+
variants={pageVariants}
251+
transition={pageTransition}
252+
>
253+
<DndEpisodePage />
254+
</motion.div>
255+
}
256+
/>
209257
{/* D&D specific 404 page */}
210258
<Route
211259
path="/dnd/*"

src/components/DndCard.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import React from 'react';
22
import { Link } from 'react-router-dom';
33
import '../styles/dnd.css';
44

5-
const DndCard = ({ title, description, link }) => {
5+
const DndCard = ({ title, author, link, backgroundImage, className }) => {
66
return (
7-
<Link to={link} className="dnd-card">
7+
<Link to={link} className={`dnd-card ${className || ''}`} style={{ backgroundImage: `url(${backgroundImage})` }}>
88
<h3>{title}</h3>
9-
<p>{description}</p>
9+
{author && <p className="author-text">{author}</p>}
1010
</Link>
1111
);
1212
};

src/components/DndFooter.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
import React, { useContext } from 'react';
22
import { DndContext } from '../context/DndContext';
3+
import DndLogo from './DndLogo'; // Import DndLogo
34

45
const DndFooter = () => {
56
const { bgImageName } = useContext(DndContext);
67

78
return (
89
<footer className="dnd-footer">
9-
<div className="dnd-footer-left">
10-
<p>&copy; 2025 From Serfs and Frauds. All rights reserved.</p>
10+
<div className="dnd-footer-logo-section">
11+
<DndLogo />
12+
<p className="dnd-footer-copyright">From Serfs and Frauds</p>
13+
</div>
14+
<div className="dnd-footer-column">
15+
<h3>About Us</h3>
16+
<p>We are a group of adventurers and storytellers, dedicated to bringing you epic tales from the realms of fantasy.</p>
1117
</div>
12-
<div className="dnd-footer-right">
13-
<p> Unsplash: {bgImageName}</p>
18+
<div className="dnd-footer-column">
19+
<h3>Legal & Info</h3>
20+
<p>&copy; 2025 From Serfs and Frauds. All rights reserved.</p>
21+
<p>Unsplash: {bgImageName}</p>
1422
</div>
1523
</footer>
1624
);

src/components/DndNavbar.js

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,46 @@
1-
import React from 'react';
1+
import React, { useContext } from 'react';
22
import { Link } from 'react-router-dom';
33
import DndLogo from './DndLogo';
4+
import { DndContext } from '../context/DndContext'; // Import DndContext
45

56
const DndNavbar = () => {
7+
const { breadcrumbs } = useContext(DndContext); // Get breadcrumbs from context
8+
9+
const formatBreadcrumbLabel = (label) => {
10+
const colonIndex = label.indexOf(':');
11+
return colonIndex !== -1 ? label.substring(0, colonIndex) : label;
12+
};
13+
614
return (
715
<nav className="dnd-navbar">
816
<div className="dnd-navbar-left">
9-
<Link to="/" className="dnd-navbar-link">Back to Home</Link>
17+
{breadcrumbs && breadcrumbs.length > 0 ? (
18+
<div className="dnd-breadcrumbs">
19+
{breadcrumbs.map((crumb, index) => (
20+
<React.Fragment key={crumb.path || index}>
21+
{index > 0 && <span className="dnd-breadcrumb-separator">&rarr;</span>}
22+
{crumb.path ? (
23+
<Link to={crumb.path} className="dnd-breadcrumb-link">{formatBreadcrumbLabel(crumb.label)}</Link>
24+
) : (
25+
<span className="dnd-breadcrumb-current">{formatBreadcrumbLabel(crumb.label)}</span>
26+
)}
27+
</React.Fragment>
28+
))}
29+
</div>
30+
) : (
31+
<Link to="/" className="dnd-navbar-link">Back to Home</Link>
32+
)}
1033
</div>
1134
<div className="dnd-navbar-center">
12-
<span className="dnd-navbar-title">From Serfs and Frauds</span>
13-
</div>
14-
<div className="dnd-navbar-right">
15-
<DndLogo />
35+
<Link to="/" className="flex items-center space-x-2">
36+
<span className="text-2xl font-semibold tracking-tight text-white">
37+
fez<span className="text-primary-400">codex</span>
38+
</span>
39+
</Link>
1640
</div>
41+
<div className="dnd-navbar-right">
42+
<DndLogo />
43+
</div>
1744
</nav>
1845
);
1946
};

0 commit comments

Comments
 (0)