diff --git a/src/client/views/guild/content.ejs b/src/client/views/guild/content.ejs
new file mode 100644
index 0000000..047ddab
--- /dev/null
+++ b/src/client/views/guild/content.ejs
@@ -0,0 +1,5 @@
+<% layout("layout/base") -%>
+
+<%- include("header") -%>
+
+Content page placeholder
\ No newline at end of file
diff --git a/src/client/views/guild/feeds.ejs b/src/client/views/guild/feeds.ejs
new file mode 100644
index 0000000..78b8ea8
--- /dev/null
+++ b/src/client/views/guild/feeds.ejs
@@ -0,0 +1,5 @@
+<% layout("layout/base") -%>
+
+<%- include("header") -%>
+
+Feeds page placeholder
\ No newline at end of file
diff --git a/src/client/views/guild/filters.ejs b/src/client/views/guild/filters.ejs
new file mode 100644
index 0000000..5071d92
--- /dev/null
+++ b/src/client/views/guild/filters.ejs
@@ -0,0 +1,5 @@
+<% layout("layout/base") -%>
+
+<%- include("header") -%>
+
+Filters page placeholder
\ No newline at end of file
diff --git a/src/client/views/guild/header.ejs b/src/client/views/guild/header.ejs
new file mode 100644
index 0000000..69cad55
--- /dev/null
+++ b/src/client/views/guild/header.ejs
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+ <% if (guild.icon) { %>
+
 %>)
+ <% } else { %>
+
+ <%= guild.nameAcronym %>
+
+ <% } %>
+
+
+
+
+
+ <%= guild.name %>
+
+
+ -
+ ID:
+ <%= guild.id %>
+
+ -
+ Members:
+ <%= guild.memberCount %>
+
+ -
+ Channels:
+ <%= guild.channels.channelCountWithoutThreads %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/client/views/guild/styles.ejs b/src/client/views/guild/styles.ejs
new file mode 100644
index 0000000..379c9d7
--- /dev/null
+++ b/src/client/views/guild/styles.ejs
@@ -0,0 +1,5 @@
+<% layout("layout/base") -%>
+
+<%- include("header") -%>
+
+Styles page placeholder
\ No newline at end of file
diff --git a/src/server/controllers/guild/content.controller.ts b/src/server/controllers/guild/content.controller.ts
new file mode 100644
index 0000000..2c5c11a
--- /dev/null
+++ b/src/server/controllers/guild/content.controller.ts
@@ -0,0 +1,19 @@
+import { Request, Response } from "express";
+import { client as bot } from "@bot/bot";
+
+export const get = async (request: Request, response: Response) => {
+ const guildId = request.params.guildId;
+ const guild = bot.guilds.cache.get(guildId);
+
+ if (!guild) {
+ response.status(404).send("404: guild not found");
+ return;
+ }
+
+ response.render("guild/content", {
+ title: `${guild.name} - Relay`,
+ guild: guild
+ });
+};
+
+export default { get }
\ No newline at end of file
diff --git a/src/server/controllers/guild/feed.controller.ts b/src/server/controllers/guild/feed.controller.ts
new file mode 100644
index 0000000..3da9342
--- /dev/null
+++ b/src/server/controllers/guild/feed.controller.ts
@@ -0,0 +1,19 @@
+import { Request, Response } from "express";
+import { client as bot } from "@bot/bot";
+
+export const get = async (request: Request, response: Response) => {
+ const guildId = request.params.guildId;
+ const guild = bot.guilds.cache.get(guildId);
+
+ if (!guild) {
+ response.status(404).send("404: guild not found");
+ return;
+ }
+
+ response.render("guild/feeds", {
+ title: `${guild.name} - Relay`,
+ guild: guild
+ });
+};
+
+export default { get }
\ No newline at end of file
diff --git a/src/server/controllers/guild/filter.controller.ts b/src/server/controllers/guild/filter.controller.ts
new file mode 100644
index 0000000..eb1dd7e
--- /dev/null
+++ b/src/server/controllers/guild/filter.controller.ts
@@ -0,0 +1,19 @@
+import { Request, Response } from "express";
+import { client as bot } from "@bot/bot";
+
+export const get = async (request: Request, response: Response) => {
+ const guildId = request.params.guildId;
+ const guild = bot.guilds.cache.get(guildId);
+
+ if (!guild) {
+ response.status(404).send("404: guild not found");
+ return;
+ }
+
+ response.render("guild/filters", {
+ title: `${guild.name} - Relay`,
+ guild: guild
+ });
+};
+
+export default { get }
\ No newline at end of file
diff --git a/src/server/controllers/guild/style.controller.ts b/src/server/controllers/guild/style.controller.ts
new file mode 100644
index 0000000..f0758f1
--- /dev/null
+++ b/src/server/controllers/guild/style.controller.ts
@@ -0,0 +1,19 @@
+import { Request, Response } from "express";
+import { client as bot } from "@bot/bot";
+
+export const get = async (request: Request, response: Response) => {
+ const guildId = request.params.guildId;
+ const guild = bot.guilds.cache.get(guildId);
+
+ if (!guild) {
+ response.status(404).send("404: guild not found");
+ return;
+ }
+
+ response.render("guild/styles", {
+ title: `${guild.name} - Relay`,
+ guild: guild
+ });
+};
+
+export default { get }
\ No newline at end of file
diff --git a/src/server/middleware/attachGuilds.ts b/src/server/middleware/attachGuilds.ts
index 5b4f3ed..b019e4c 100644
--- a/src/server/middleware/attachGuilds.ts
+++ b/src/server/middleware/attachGuilds.ts
@@ -1,6 +1,9 @@
import { Request, Response, NextFunction } from "express";
import { client as bot } from "@bot/bot";
+// The purpose of this middleware is to attach an object containing cached
+// Discord servers to the response, which is accessible in the DOM.
+// This is primarily used for rendering servers on the sidebar.
export const attachGuilds = (_request: Request, response: Response, next: NextFunction) => {
response.locals.guilds = bot.guilds.cache.map(guild => guild);
next();
diff --git a/src/server/routers/guild.router.ts b/src/server/routers/guild.router.ts
new file mode 100644
index 0000000..bb0e77d
--- /dev/null
+++ b/src/server/routers/guild.router.ts
@@ -0,0 +1,21 @@
+import { Request, Response, Router } from "express";
+
+import feedController from "@server/controllers/guild/feed.controller";
+import filterController from "@server/controllers/guild/filter.controller";
+import styleController from "@server/controllers/guild/style.controller";
+import contentController from "@server/controllers/guild/content.controller";
+
+const router = Router();
+
+router.get("/:guildId", (request: Request, response: Response) => {
+ const guildId = request.params.guildId;
+ response.redirect(`/guild/${guildId}/feeds`);
+ return;
+});
+
+router.get("/:guildId/feeds", feedController.get);
+router.get("/:guildId/filters", filterController.get);
+router.get("/:guildId/styles", styleController.get);
+router.get("/:guildId/content", contentController.get);
+
+export default router;
\ No newline at end of file