diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts
index c81506384..446df1554 100644
--- a/packages/backend/src/server/web/index.ts
+++ b/packages/backend/src/server/web/index.ts
@@ -232,8 +232,43 @@ const getFeed = async (acct: string) => {
 	return user && await packFeed(user);
 };
 
+// As the /@user[.json|.rss|.atom]/sub endpoint is complicated, we will use a regex to switch between them.
+const reUser = new RegExp(`^/@(?<user>[^/]+?)(?:\.(?<feed>json|rss|atom))?(?:/(?<sub>[^/]+))?$`);
+router.get(reUser, async (ctx, next) => {
+	const groups = reUser.exec(ctx.originalUrl)?.groups;
+	if (!groups) {
+		await next();
+		return;
+	}
+
+	ctx.params = groups;
+
+	console.log(ctx, ctx.params)
+	if (groups.feed) {
+		if (groups.sub) {
+			await next();
+			return;
+		}
+
+		switch (groups.feed) {
+			case 'json':
+				await jsonFeed(ctx, next);
+				break;
+			case 'rss':
+				await rssFeed(ctx, next);
+				break;
+			case 'atom':
+				await atomFeed(ctx, next);
+				break;
+		}
+		return;
+	}
+
+	await userPage(ctx, next);
+});
+
 // Atom
-router.get('/@:user.atom', async ctx => {
+const atomFeed: Router.Middleware = async ctx => {
 	const feed = await getFeed(ctx.params.user);
 
 	if (feed) {
@@ -242,10 +277,10 @@ router.get('/@:user.atom', async ctx => {
 	} else {
 		ctx.status = 404;
 	}
-});
+};
 
 // RSS
-router.get('/@:user.rss', async ctx => {
+const rssFeed: Router.Middleware = async ctx => {
 	const feed = await getFeed(ctx.params.user);
 
 	if (feed) {
@@ -254,10 +289,10 @@ router.get('/@:user.rss', async ctx => {
 	} else {
 		ctx.status = 404;
 	}
-});
+};
 
 // JSON
-router.get('/@:user.json', async ctx => {
+const jsonFeed: Router.Middleware = async ctx => {
 	const feed = await getFeed(ctx.params.user);
 
 	if (feed) {
@@ -266,43 +301,47 @@ router.get('/@:user.json', async ctx => {
 	} else {
 		ctx.status = 404;
 	}
-});
+};
 
 //#region SSR (for crawlers)
 // User
-router.get(['/@:user', '/@:user/:sub'], async (ctx, next) => {
-	const { username, host } = Acct.parse(ctx.params.user);
+const userPage: Router.Middleware = async (ctx, next) => {
+	const userParam = ctx.params.user;
+	const subParam = ctx.params.sub;
+	const { username, host } = Acct.parse(userParam);
+
 	const user = await Users.findOneBy({
 		usernameLower: username.toLowerCase(),
 		host: host ?? IsNull(),
 		isSuspended: false,
 	});
 
-	if (user != null) {
-		const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
-		const meta = await fetchMeta();
-		const me = profile.fields
-			? profile.fields
-				.filter(filed => filed.value != null && filed.value.match(/^https?:/))
-				.map(field => field.value)
-			: [];
-
-		await ctx.render('user', {
-			user, profile, me,
-			avatarUrl: await Users.getAvatarUrl(user),
-			sub: ctx.params.sub,
-			instanceName: meta.name || 'Calckey',
-			icon: meta.iconUrl,
-			themeColor: meta.themeColor,
-			privateMode: meta.privateMode,
-		});
-		ctx.set('Cache-Control', 'public, max-age=15');
-	} else {
-		// リモートユーザーなので
-		// モデレータがAPI経由で参照可能にするために404にはしない
+	if (user === null) {
 		await next();
+		return;
 	}
-});
+
+	const profile = await UserProfiles.findOneByOrFail({ userId: user.id });
+	const meta = await fetchMeta();
+	const me = profile.fields
+		? profile.fields
+			.filter(filed => filed.value != null && filed.value.match(/^https?:/))
+			.map(field => field.value)
+		: [];
+
+	const userDetail = {
+		user, profile, me,
+		avatarUrl: await Users.getAvatarUrl(user),
+		sub: subParam,
+		instanceName: meta.name || 'Calckey',
+		icon: meta.iconUrl,
+		themeColor: meta.themeColor,
+		privateMode: meta.privateMode,
+	};
+
+	await ctx.render('user', userDetail);
+	ctx.set('Cache-Control', 'public, max-age=15');
+};
 
 router.get('/users/:user', async ctx => {
 	const user = await Users.findOneBy({
diff --git a/packages/client/src/components/MkNote.vue b/packages/client/src/components/MkNote.vue
index 80441f34d..597d20c5b 100644
--- a/packages/client/src/components/MkNote.vue
+++ b/packages/client/src/components/MkNote.vue
@@ -426,7 +426,8 @@ function readPromo() {
 	> .article {
 		display: flex;
 		padding: 28px 32px 18px;
-
+		cursor: pointer;
+		
 		> .avatar {
 			flex-shrink: 0;
 			display: block;
diff --git a/packages/client/src/components/MkNoteDetailed.vue b/packages/client/src/components/MkNoteDetailed.vue
index 19feacec4..233143ca6 100644
--- a/packages/client/src/components/MkNoteDetailed.vue
+++ b/packages/client/src/components/MkNoteDetailed.vue
@@ -346,6 +346,8 @@ if (appearNote.replyId) {
 
 	> .reply-to-more {
 		opacity: 0.7;
+		cursor: pointer;
+		
 	}
 
 	> .renote {
@@ -543,6 +545,7 @@ if (appearNote.replyId) {
 
 	> .reply {
 		border-top: solid 0.5px var(--divider);
+		cursor: pointer;
 	}
 
 	> .reply, .reply-to, .reply-to-more {
diff --git a/packages/client/src/components/MkNoteSub.vue b/packages/client/src/components/MkNoteSub.vue
index c8041be42..c1943920d 100644
--- a/packages/client/src/components/MkNoteSub.vue
+++ b/packages/client/src/components/MkNoteSub.vue
@@ -65,6 +65,7 @@ const replies: misskey.entities.Note[] = props.conversation?.filter(item => item
 	&.children {
 		padding: 10px 0 0 16px;
 		font-size: 1em;
+		cursor: auto;
 
 		&.max-width_450px {
 			padding: 10px 0 0 8px;
@@ -86,9 +87,11 @@ const replies: misskey.entities.Note[] = props.conversation?.filter(item => item
 		> .body {
 			flex: 1;
 			min-width: 0;
-
+			cursor: pointer;
+			
 			> .header {
 				margin-bottom: 2px;
+				cursor: auto;
 			}
 
 			> .body {