Skip to content

Commit b94658c

Browse files
Copilotmahata
andauthored
Add public /about page describing the project (#59)
* Initial plan * Add public /about page with minimal design Co-authored-by: mahata <[email protected]> * Change "MLack" to "Mlack" in About page branding Co-authored-by: mahata <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: mahata <[email protected]>
1 parent 9c9fcb4 commit b94658c

File tree

6 files changed

+404
-9
lines changed

6 files changed

+404
-9
lines changed

hono/components/AboutPage.css

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/* Base styles for the about page - consistent with ChatPage */
2+
body {
3+
font-family: Arial, sans-serif;
4+
max-width: 800px;
5+
margin: 0 auto;
6+
padding: 20px;
7+
background-color: #f5f5f5;
8+
}
9+
10+
/* Container styles */
11+
.about-container {
12+
background-color: white;
13+
border-radius: 8px;
14+
padding: 20px;
15+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
16+
}
17+
18+
.page-title {
19+
color: #333;
20+
text-align: center;
21+
margin-bottom: 20px;
22+
}
23+
24+
/* Content styles */
25+
.content {
26+
line-height: 1.6;
27+
color: #333;
28+
margin-bottom: 30px;
29+
}
30+
31+
.content p {
32+
margin-bottom: 16px;
33+
}
34+
35+
.content a {
36+
color: #2196f3;
37+
text-decoration: none;
38+
}
39+
40+
.content a:hover {
41+
color: #1976d2;
42+
text-decoration: underline;
43+
}
44+
45+
/* Navigation styles */
46+
.navigation {
47+
text-align: center;
48+
padding-top: 20px;
49+
border-top: 1px solid #ddd;
50+
}
51+
52+
.back-link {
53+
color: #2196f3;
54+
text-decoration: none;
55+
padding: 10px 20px;
56+
border: 1px solid #2196f3;
57+
border-radius: 4px;
58+
background-color: transparent;
59+
transition: background-color 0.2s;
60+
}
61+
62+
.back-link:hover {
63+
background-color: #2196f3;
64+
color: white;
65+
text-decoration: none;
66+
}

hono/components/AboutPage.test.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { describe, expect, it } from "vitest";
2+
import { AboutPage } from "./AboutPage.js";
3+
4+
describe("AboutPage component", () => {
5+
it("should include CSS stylesheet", async () => {
6+
const jsxElement = await AboutPage();
7+
8+
const html = jsxElement.toString();
9+
expect(html).toContain('href="/components/AboutPage.css"');
10+
});
11+
12+
it("should contain required content about the project", async () => {
13+
const jsxElement = await AboutPage();
14+
15+
const html = jsxElement.toString();
16+
17+
// Check for all required content elements
18+
expect(html).toContain("About Mlack");
19+
expect(html).toContain("Slack-like application that&#39;s fully open source");
20+
expect(html).toContain("@mahata/mlack");
21+
expect(html).toContain("experimental project");
22+
expect(html).toContain("Vibe Coding");
23+
expect(html).toContain("90% of the code is written by");
24+
expect(html).toContain("GitHub Copilot Coding Agent");
25+
});
26+
27+
it("should have proper navigation back to main page", async () => {
28+
const jsxElement = await AboutPage();
29+
30+
const html = jsxElement.toString();
31+
expect(html).toContain('href="/"');
32+
expect(html).toContain("← Back to Chat");
33+
});
34+
35+
it("should have proper HTML structure", async () => {
36+
const jsxElement = await AboutPage();
37+
38+
const html = jsxElement.toString();
39+
expect(html).toContain('<html lang="en">');
40+
expect(html).toContain("<title>About - Mlack</title>");
41+
expect(html).toContain('class="about-container"');
42+
expect(html).toContain('class="page-title"');
43+
expect(html).toContain('class="content"');
44+
expect(html).toContain('class="navigation"');
45+
});
46+
47+
it("should include external links with proper attributes", async () => {
48+
const jsxElement = await AboutPage();
49+
50+
const html = jsxElement.toString();
51+
52+
// Check that external links have proper security attributes
53+
expect(html).toContain('target="_blank"');
54+
expect(html).toContain('rel="noopener noreferrer"');
55+
56+
// Check for the GitHub link
57+
expect(html).toContain('href="https://github.com/mahata/mlack"');
58+
59+
// Check for the Copilot documentation link
60+
expect(html).toContain('href="https://docs.github.com/en/copilot/concepts/about-copilot-coding-agent"');
61+
});
62+
});

hono/components/AboutPage.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
export async function AboutPage() {
2+
return (
3+
<html lang="en">
4+
<head>
5+
<meta charSet="UTF-8" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>About - Mlack</title>
8+
<link rel="stylesheet" href="/components/AboutPage.css" />
9+
</head>
10+
<body>
11+
<div className="about-container">
12+
<h1 className="page-title">About Mlack</h1>
13+
14+
<div className="content">
15+
<p>
16+
Mlack is a Slack-like application that's fully open source.
17+
The source code is available at <a href="https://github.com/mahata/mlack" target="_blank" rel="noopener noreferrer">@mahata/mlack</a>.
18+
</p>
19+
20+
<p>
21+
This is an experimental project designed to build a real-world application using "Vibe Coding".
22+
Around 90% of the code is written by{" "}
23+
<a href="https://docs.github.com/en/copilot/concepts/about-copilot-coding-agent" target="_blank" rel="noopener noreferrer">
24+
GitHub Copilot Coding Agent
25+
</a>.
26+
</p>
27+
28+
<p>
29+
The project explores what's possible when combining human creativity with AI assistance
30+
to rapidly prototype and build functional applications.
31+
</p>
32+
</div>
33+
34+
<div className="navigation">
35+
<a href="/" className="back-link">← Back to Chat</a>
36+
</div>
37+
</div>
38+
</body>
39+
</html>
40+
);
41+
}

hono/routes/index.test.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,30 @@ describe("Root page", () => {
8282
expect(response.status).toBe(302);
8383
expect(response.headers.get("Location")).toBe("/auth/google");
8484
});
85+
86+
it("should return the About page without authentication", async () => {
87+
// Create a test app with an unauthenticated user
88+
const { app: testAppNoAuth } = createTestApp({ authenticatedUser: null });
89+
90+
// Add the index route to the test app
91+
const { index } = await import("./index.js");
92+
testAppNoAuth.route("/", index);
93+
94+
const response = await testAppNoAuth.request("/about");
95+
96+
expect(response.status).toBe(200);
97+
expect(response.headers.get("Content-Type")).toBe("text/html; charset=UTF-8");
98+
99+
const html = await response.text();
100+
101+
// Check for About page specific content
102+
expect(html).toContain("<title>About - Mlack</title>");
103+
expect(html).toContain("About Mlack");
104+
expect(html).toContain("Slack-like application that&#39;s fully open source");
105+
expect(html).toContain("@mahata/mlack");
106+
expect(html).toContain("GitHub Copilot Coding Agent");
107+
expect(html).toContain("Vibe Coding");
108+
expect(html).toContain("← Back to Chat");
109+
expect(html).toContain('href="/components/AboutPage.css"');
110+
});
85111
});

hono/routes/index.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Hono } from "hono";
2+
import { AboutPage } from "../components/AboutPage.js";
23
import { ChatPage } from "../components/ChatPage.js";
34
import type { Variables } from "../types.js";
45

@@ -29,4 +30,8 @@ index.get("/", async (c) => {
2930
return c.html(`<!DOCTYPE html>${await ChatPage(wsUrl, user)}`);
3031
});
3132

33+
index.get("/about", async (c) => {
34+
return c.html(`<!DOCTYPE html>${await AboutPage()}`);
35+
});
36+
3237
export { index };

0 commit comments

Comments
 (0)