Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ jobs:
node-version: '20'
cache: 'npm'

- name: Use project npm version
run: npm install --global npm@11.6.1

- name: Install dependencies
run: npm ci

Expand Down
2 changes: 2 additions & 0 deletions apps/lms/app/(home)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export const metadata: Metadata = {
title: "BeeWise LMS | Hệ Thống Quản Lý Học Tập Thông Minh",
description:
"Không gian làm việc và học tập của Gia sư và Học viên. Số hóa lịch trình, lưu trữ tài liệu và tối ưu hóa hiệu quả dạy & học trên BeeWise LMS.",
alternates: { canonical: "/" },
robots: { index: true, follow: true },
};

export default function LmsHomePage() {
Expand Down
2 changes: 2 additions & 0 deletions apps/lms/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import "@workspace/ui/globals.css";
import { Metadata } from "next";
import { googleSans, nunito } from "@workspace/core/configs/fonts";
import { TooltipProvider } from "@workspace/ui/components/ui/tooltip";
import { lmsSeoConfig } from "@/configs/seo";

export const metadata: Metadata = {
metadataBase: new URL(lmsSeoConfig.siteUrl),
title: "BeeWise LMS | Hệ Thống Quản Lý Học Tập Thông Minh",
};

Expand Down
14 changes: 14 additions & 0 deletions apps/lms/app/robots.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { MetadataRoute } from "next";
import { getLmsUrl, lmsSeoConfig } from "@/configs/seo";

export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: "*",
allow: ["/", "/login"],
disallow: "/lms/",
},
sitemap: getLmsUrl("/sitemap.xml"),
host: lmsSeoConfig.siteUrl,
};
}
6 changes: 6 additions & 0 deletions apps/lms/app/sitemap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { MetadataRoute } from "next";
import { getLmsUrl } from "@/configs/seo";

export default function sitemap(): MetadataRoute.Sitemap {
return [{ url: getLmsUrl("/") }];
}
30 changes: 30 additions & 0 deletions apps/lms/configs/seo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const DEFAULT_LMS_SITE_URL = "https://superlms.beewise.vn";

function resolveSiteUrl(value: string | undefined, fallback: string): string {
if (!value) {
return fallback;
}

try {
const url = new URL(value);

if (url.protocol !== "https:" && url.protocol !== "http:") {
return fallback;
}

return url.origin;
} catch {
return fallback;
}
}

export const lmsSeoConfig = {
siteUrl: resolveSiteUrl(
process.env.NEXT_PUBLIC_SITE_URL,
DEFAULT_LMS_SITE_URL,
),
} as const;

export function getLmsUrl(pathname: string): string {
return new URL(pathname, `${lmsSeoConfig.siteUrl}/`).toString();
}
2 changes: 1 addition & 1 deletion apps/lms/proxy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

const publicPaths = ["/", "/login"];
const publicPaths = ["/", "/login", "/robots.txt", "/sitemap.xml"];

export function proxy(request: NextRequest) {
const { pathname } = request.nextUrl;
Expand Down
1 change: 1 addition & 0 deletions apps/sale/app/(guest)/about-us/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const metadata: Metadata = {
locale: "vi_VN",
siteName: "BeeWise",
},
alternates: { canonical: "/about-us" },
};

export default function AboutPage() {
Expand Down
1 change: 1 addition & 0 deletions apps/sale/app/(guest)/favorite-tutors/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { FavoriteTutorsPage } from "../../../features/favorite-tutors/components
export const metadata: Metadata = {
title: "Gia sư yêu thích | BeeWise",
description: "Danh sách các gia sư bạn đã lưu lại trên hệ thống BeeWise.",
robots: { index: false, follow: false },
};

import { Header } from "@workspace/ui/components/layout/Header";
Expand Down
1 change: 1 addition & 0 deletions apps/sale/app/(guest)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export const metadata: Metadata = {
description:
"Tìm gia sư phù hợp trong 30 giây với AI. Hồ sơ xác thực, cố vấn đồng hành, miễn phí.",
},
alternates: { canonical: "/" },
robots: {
index: true,
follow: true,
Expand Down
1 change: 1 addition & 0 deletions apps/sale/app/(guest)/tutor-guide/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const metadata: Metadata = {
"nền tảng gia sư",
"BeeWise",
],
alternates: { canonical: "/tutor-guide" },
};

export default function TutorGuidePage() {
Expand Down
1 change: 1 addition & 0 deletions apps/sale/app/(guest)/tutors/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const metadata: Metadata = {
"BeeWise",
"tìm gia sư AI",
],
alternates: { canonical: "/tutors" },
};

export default function TutorListPage() {
Expand Down
2 changes: 2 additions & 0 deletions apps/sale/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import "@workspace/ui/globals.css";
import { Metadata } from "next";
import { GuestFavoriteModal } from "@/features/favorite-tutors/components/GuestFavoriteModal";
import { NotificationDrawer } from "@/features/notifications/components/NotificationDrawer";
import { saleSeoConfig } from "@/configs/seo";

export const metadata: Metadata = {
metadataBase: new URL(saleSeoConfig.siteUrl),
title: "Cộng đồng gia sư",
};

Expand Down
14 changes: 14 additions & 0 deletions apps/sale/app/robots.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { MetadataRoute } from "next";
import { getSaleUrl, saleSeoConfig } from "@/configs/seo";

export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: "*",
allow: "/",
disallow: [...saleSeoConfig.privateRoutes],
},
sitemap: getSaleUrl("/sitemap.xml"),
host: saleSeoConfig.siteUrl,
};
}
8 changes: 8 additions & 0 deletions apps/sale/app/sitemap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { MetadataRoute } from "next";
import { getSaleUrl, saleSeoConfig } from "@/configs/seo";

export default function sitemap(): MetadataRoute.Sitemap {
return saleSeoConfig.indexableRoutes.map((route) => ({
url: getSaleUrl(route),
}));
}
38 changes: 38 additions & 0 deletions apps/sale/configs/seo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const DEFAULT_SALE_SITE_URL = "https://beewise.vn";

function resolveSiteUrl(value: string | undefined, fallback: string): string {
if (!value) {
return fallback;
}

try {
const url = new URL(value);

if (url.protocol !== "https:" && url.protocol !== "http:") {
return fallback;
}

return url.origin;
} catch {
return fallback;
}
}

export const saleSeoConfig = {
siteUrl: resolveSiteUrl(
process.env.NEXT_PUBLIC_SITE_URL,
DEFAULT_SALE_SITE_URL,
),
indexableRoutes: ["/", "/tutors", "/tutor-guide", "/about-us"],
privateRoutes: [
"/learner/",
"/tutor/",
"/community/applications",
"/community/my-posts",
"/dev/",
],
} as const;

export function getSaleUrl(pathname: string): string {
return new URL(pathname, `${saleSeoConfig.siteUrl}/`).toString();
}
56 changes: 45 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading