diff --git a/src/components/Card/Card.astro b/src/components/Card/Card.astro
new file mode 100644
index 0000000..6ac263d
--- /dev/null
+++ b/src/components/Card/Card.astro
@@ -0,0 +1,75 @@
+---
+import Svg from "@cxa/astro-inline-svg";
+import { Icon } from "astro-icon/components";
+
+import "../../styles/global.css";
+import { generateQRCode } from "../../libs/qrcode.ts";
+
+export type Props = { url: string };
+const { url } = Astro.props;
+
+const { hostname } = new URL(url);
+const qrCode: string = await generateQRCode(url);
+---
+
+
+
+
+
+ {hostname}
+
+
+
+
diff --git a/src/components/Card/Card.stories.ts b/src/components/Card/Card.stories.ts
new file mode 100644
index 0000000..055f455
--- /dev/null
+++ b/src/components/Card/Card.stories.ts
@@ -0,0 +1,10 @@
+import Card from "./Card.astro";
+import * as stories from "./story.ts";
+
+export default {
+ title: "Card",
+ component: Card,
+};
+
+export const Default = { args: stories.Default };
+export const SubDomain = { args: stories.SubDomain };
diff --git a/src/components/Card/Card.test.ts b/src/components/Card/Card.test.ts
new file mode 100644
index 0000000..579ae23
--- /dev/null
+++ b/src/components/Card/Card.test.ts
@@ -0,0 +1,31 @@
+import { experimental_AstroContainer as AstroContainer } from "astro/container";
+import { describe, expect, test } from "vitest";
+
+import Card from "./Card.astro";
+import type { Props } from "./Card.astro";
+import * as stories from "./story.ts";
+
+describe("Card", () => {
+ describe("Valid URL", () => {
+ for (const [name, props] of Object.entries(stories)) {
+ test(name, async () => {
+ const container: AstroContainer = await AstroContainer.create();
+ const result: string = await container.renderToString(Card, {
+ props,
+ });
+
+ expect(result).toMatchSnapshot();
+ });
+ }
+ });
+
+ test("Invalid URL", async () => {
+ const container: AstroContainer = await AstroContainer.create();
+
+ await expect(
+ container.renderToString(Card, {
+ props: { url: "not-valid-url" } satisfies Props,
+ }),
+ ).rejects.toThrow();
+ });
+});
diff --git a/src/components/Card/__snapshots__/Card.test.ts.snap b/src/components/Card/__snapshots__/Card.test.ts.snap
new file mode 100644
index 0000000..11d5128
--- /dev/null
+++ b/src/components/Card/__snapshots__/Card.test.ts.snap
@@ -0,0 +1,5 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`Card > Valid URL > Default 1`] = `" "`;
+
+exports[`Card > Valid URL > SubDomain 1`] = `" "`;
diff --git a/src/components/Card/story.ts b/src/components/Card/story.ts
new file mode 100644
index 0000000..6c0f849
--- /dev/null
+++ b/src/components/Card/story.ts
@@ -0,0 +1,4 @@
+import type { Props } from "./Card.astro";
+
+export const Default: Props = { url: "https://example.com" };
+export const SubDomain: Props = { url: "https://www.example.com" };