diff --git a/.cli/package.cts b/.cli/package.cts new file mode 100644 index 0000000..dd2220e --- /dev/null +++ b/.cli/package.cts @@ -0,0 +1,78 @@ +import path from "node:path"; +import chalk from "chalk"; +import { Command } from "commander"; +import { mkdirSync, writeFileSync } from "fs-extra"; +import inquirer from "inquirer"; + +const program = new Command(); + +program.name("repo-cli").description("모노레포 프로젝트를 위한 패키지 생성기").version("1.0.0"); + +async function createPackage() { + const answers = await inquirer.prompt([ + { + type: "input", + name: "projectName", + message: "Enter a package name", + validate: (input: string) => !!input || "Enter a package name", + }, + { + type: "list", + name: "tsconfig", + message: "Choose a tsconfig", + choices: ["base.json", "react-library.json", "nextjs.json"], + }, + ]); + + const projectName = answers.projectName; + const tsconfig = answers.tsconfig; + + const packagePath = path.resolve(process.cwd(), `packages/${projectName}`); + const srcPath = path.join(packagePath, "src"); + const indexPath = path.join(srcPath, "index.ts"); + const packageJsonPath = path.join(packagePath, "package.json"); + const tsconfigPath = path.join(packagePath, "tsconfig.json"); + + try { + // 패키지 디렉토리 생성 + mkdirSync(packagePath, { recursive: true }); + + // src 디렉토리와 index.ts 생성 + mkdirSync(srcPath, { recursive: true }); + writeFileSync(indexPath, ""); // 빈 파일 생성 + + // package.json 생성 + const packageJson = { + name: `@repo/${projectName}`, + version: "0.0.0", + main: "index.js", + devDependencies: { + "@repo/typescript-config": "workspace:*", + typescript: "latest", + }, + }; + writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); + + // tsconfig.json 생성 + const tsconfigContent = { + extends: `@repo/typescript-config/${tsconfig}`, + compilerOptions: { + outDir: "dist", + rootDir: "src", + }, + include: ["src"], + exclude: ["node_modules", "dist"], + }; + writeFileSync(tsconfigPath, JSON.stringify(tsconfigContent, null, 2)); + } catch (err) { + if (err instanceof Error) { + console.error(chalk.red(`❌ 패키지 생성 중 에러가 발생했습니다: ${err.message}`)); + } else { + console.error(chalk.red(`❌ 패키지 생성 중 알 수 없는 에러가 발생했습니다.`)); + } + } +} + +program.action(createPackage); + +program.parse(process.argv); diff --git a/.github/workflows/pr-size-labeler.yml b/.github/workflows/pr-size-labeler.yml index 1951863..020adae 100644 --- a/.github/workflows/pr-size-labeler.yml +++ b/.github/workflows/pr-size-labeler.yml @@ -1,4 +1,4 @@ -name: labeler +name: Pr Size Labeler on: [pull_request] @@ -27,5 +27,8 @@ jobs: This PR exceeds the recommended size of 1000 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size. - github_api_url: 'https://api.github.com' - files_to_ignore: 'pnpm-lock.yaml' \ No newline at end of file + github_api_url: "https://api.github.com" + files_to_ignore: | + pnpm-lock.yaml + package-lock.json + yarn.lock diff --git a/.gitignore b/.gitignore index f57a799..897bce3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,8 @@ node_modules .env.test.local .env.production.local +storybook-static + # Testing coverage @@ -40,3 +42,5 @@ yarn-error.log* # Misc .DS_Store *.pem + +*storybook.log diff --git a/.ncurc.json b/.ncurc.json index 7b7ee56..e096d8a 100644 --- a/.ncurc.json +++ b/.ncurc.json @@ -1,6 +1,6 @@ { "upgrade": true, - "target": "minor", + "target": "latest", "reject": ["tailwind-merge", "react", "react-dom", "@types/react", "@types/react-dom", "@biomejs/biome", "next"], "deep": true } diff --git a/apps/blog/app/(blog)/posts/[...slug]/page.tsx b/apps/blog/app/(blog)/posts/[...slug]/page.tsx index 58afbad..272c4e6 100644 --- a/apps/blog/app/(blog)/posts/[...slug]/page.tsx +++ b/apps/blog/app/(blog)/posts/[...slug]/page.tsx @@ -1,7 +1,7 @@ import type { Metadata } from "next"; import { redirect } from "next/navigation"; import { getAllPosts, getPost } from "~/entities/post/model/post.service"; -import PostDetailPage from "~/page/post-detail.page"; +import PostDetailPage from "~/page/PostDetailPage"; import { BASE_SITE_URL } from "~/shared/constants"; import { createMetadata } from "~/shared/utils/external/create-meta-data"; @@ -14,7 +14,9 @@ type PostProps = { export const generateMetadata = async ({ params }: PostProps): Promise => { const slug = (await params).slug; const post = await getPost(slug); - if (!post) throw new Error("Post not found"); + if (!post) { + throw new Error("Post not found"); + } const url = `${BASE_SITE_URL}/posts/${post.filePath.join("/")}`; const metaData = createMetadata({ description: post.description, title: post.title, url }); return metaData; @@ -32,6 +34,8 @@ export const dynamic = "force-static"; export default async function Post({ params }: PostProps) { const slug = (await params).slug; const post = await getPost(slug); - if (!post) return redirect("/"); + if (!post) { + return redirect("/"); + } return ; } diff --git a/apps/blog/app/(portfolio)/layout.tsx b/apps/blog/app/(portfolio)/layout.tsx deleted file mode 100644 index 6625cb5..0000000 --- a/apps/blog/app/(portfolio)/layout.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { Stack } from "@xionwcfm/xds"; -import { StaticHeader } from "~/widgets/header/static-header"; - -export default function RootLayout({ - children, -}: Readonly<{ - children: React.ReactNode; -}>) { - return ( - - - {children} - - ); -} diff --git a/apps/blog/app/(portfolio)/portfolio/page.tsx b/apps/blog/app/(portfolio)/portfolio/page.tsx deleted file mode 100644 index 10804eb..0000000 --- a/apps/blog/app/(portfolio)/portfolio/page.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { Stack } from "@xionwcfm/xds"; - -const PortfolioPage = () => { - return .; -}; - -export default PortfolioPage; diff --git a/apps/blog/app/(resume)/layout.tsx b/apps/blog/app/(resume)/layout.tsx deleted file mode 100644 index 7f819ba..0000000 --- a/apps/blog/app/(resume)/layout.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { PropsWithChildren } from "react"; - -export default function ResumeLayout({ children }: PropsWithChildren) { - return children; -} diff --git a/apps/blog/app/(resume)/resume/page.tsx b/apps/blog/app/(resume)/resume/page.tsx deleted file mode 100644 index e9b4aed..0000000 --- a/apps/blog/app/(resume)/resume/page.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { Link } from "@repo/router/link"; -import { Button, Flex, Paragraph, Pressable, Spacing, Stack } from "@xionwcfm/xds"; -import { Fragment, ReactNode } from "react"; -import { CONSTANTS } from "~/shared/constants"; - -export default function Page() { - return ( - - - - - - {LINKS.map((link) => ( - - ))} - - - - ); -} - -const ResumeTitle = () => { - return ( - - - 유길종 - - - 프론트엔드 개발자 - - - - ); -}; - -const SectionLayout = ({ children, top }: { children?: ReactNode; top?: ReactNode }) => { - return ( - - - {top} - - {children} - - ); -}; - -const LINKS = [ - { href: CONSTANTS.EXTERNAL_GITHUB, left: "Github", right: CONSTANTS.EXTERNAL_GITHUB, "aria-label": "github url" }, - { - href: CONSTANTS.EXTERNAL_LINKED_IN, - left: "LinkedIn", - right: CONSTANTS.EXTERNAL_LINKED_IN, - "aria-label": "linkedin url", - }, - { href: CONSTANTS.TECH_BLOG_URL, left: "Tech Blog", right: CONSTANTS.TECH_BLOG_URL, "aria-label": "tech blog url" }, - { href: CONSTANTS.RESUME_URL, left: "Resume", right: CONSTANTS.RESUME_URL, "aria-label": "resume url" }, -]; - -const LinkList = (props: { href: string; "aria-label": string; left: ReactNode; right: string }) => { - const { left, right, href } = props; - return ( - - - {left} - - - - - - ); -}; diff --git a/apps/blog/app/layout.tsx b/apps/blog/app/layout.tsx index 0436432..c4eafbe 100644 --- a/apps/blog/app/layout.tsx +++ b/apps/blog/app/layout.tsx @@ -2,23 +2,15 @@ import "@xionwcfm/token/style"; import "@xionwcfm/xds/style"; import "./globals.css"; -import { GoogleAnalytics, GoogleTagManager } from "@next/third-parties/google"; - +import { AnalyticsProvider } from "@repo/analytics"; +import { env } from "@repo/env"; +import { Pretendard } from "@repo/font"; import { Toaster } from "@xionwcfm/xds/toast"; import type { Metadata } from "next"; -import { Noto_Sans_KR } from "next/font/google"; -import { ClarityScript } from "~/app/script/clarity.script"; -import { ENVIRONMENT } from "~/shared/environment"; import { AUTHOR_NAME, BASE_SITE_DESCRIPTION, BASE_SITE_TITLE, BASE_SITE_URL } from "../src/shared/constants"; import { createMetadata } from "../src/shared/utils/external/create-meta-data"; import AutoRefresh from "./auto-refresh"; -const notoSansKr = Noto_Sans_KR({ - weight: ["200", "300", "500", "700"], - subsets: ["latin"], - display: "swap", -}); - export const metadata: Metadata = { ...createMetadata({ authors: AUTHOR_NAME, @@ -27,7 +19,7 @@ export const metadata: Metadata = { url: BASE_SITE_URL, }), verification: { - google: ENVIRONMENT.GSC_ID, + google: env.NEXT_PUBLIC_GSC_ID, }, }; @@ -37,16 +29,13 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - - - - {children} + + + + {children} - + - - - ); } diff --git a/apps/blog/app/page.tsx b/apps/blog/app/page.tsx index 96f3245..8f67180 100644 --- a/apps/blog/app/page.tsx +++ b/apps/blog/app/page.tsx @@ -1,24 +1,26 @@ import { Paragraph, Stack } from "@xionwcfm/xds"; import { getAllPostsSortedByReleaseDate } from "~/entities/post/model/post.service"; -import { PostCard } from "~/entities/post/ui/post/post-card"; +import { PostCard } from "~/entities/post/ui/post/PostCard"; import { AUTHOR_NICKNAME } from "~/shared/constants"; -import { MainXionWCFM } from "~/shared/ui/common/main-xion-wcfm"; -import { Separate } from "~/shared/ui/common/separate"; +import { MainXionWcfm } from "~/shared/ui/common/MainXionWcfm"; +import { Separate } from "~/shared/ui/common/Separate"; import { Footer } from "~/widgets/footer"; import { StaticHeader } from "~/widgets/header/static-header"; + export default async function RootPage() { const posts = await getAllPostsSortedByReleaseDate(); const currentPostTitle = `${AUTHOR_NICKNAME}의 최신 포스트 보기`; + return ( <> - + - + {currentPostTitle} diff --git a/apps/blog/app/sitemap.ts b/apps/blog/app/sitemap.ts index 58dd9a8..9486489 100644 --- a/apps/blog/app/sitemap.ts +++ b/apps/blog/app/sitemap.ts @@ -11,11 +11,11 @@ export default async function sitemap(): Promise { lastModified: new Date(), })); - const MAIN_URL = { + const mainUrl = { url: BASE_SITE_URL, lastModified: new Date(), }; - const allSitesMap = postUrls.concat(MAIN_URL); + const allSitesMap = postUrls.concat(mainUrl); return allSitesMap; } diff --git a/apps/blog/package.json b/apps/blog/package.json index 2b61ad6..9e84d16 100644 --- a/apps/blog/package.json +++ b/apps/blog/package.json @@ -11,63 +11,60 @@ "test": "vitest", "ci:test": "vitest run --coverage", "next-dev": "next dev", - "watch-content": "node ./watcher.cjs" + "watch-content": "node ./watcher.cjs", + "generate-types": "pnpm dlx supabase gen types typescript --project-id pzvsmsqfsintouhjavhp --schema public > types_db.ts" }, "dependencies": { - "@next/third-parties": "^14.2.18", + "@apollo/client": "^3.11.10", + "@next/third-parties": "^15.0.3", "@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-separator": "^1.1.0", - "@repo/router": "workspace:*", + "@repo/analytics": "workspace:*", + "@repo/database": "workspace:*", "@repo/date": "workspace:*", - "@repo/error": "workspace:*", + "@repo/font": "workspace:*", "@repo/icon": "workspace:*", + "@repo/mdx": "workspace:*", + "@repo/router": "workspace:*", + "@supabase/ssr": "^0.5.2", + "@supabase/supabase-js": "^2.46.2", "@xionwcfm/react": "^0.1.1", "@xionwcfm/token": "^0.2.0", "@xionwcfm/utils": "^0.0.3", "@xionwcfm/xds": "^0.2.0", - "date-fns": "^3.6.0", + "date-fns": "^4.1.0", "date-fns-tz": "^3.2.0", "next": "15.0.3", - "react": "18.3.1", - "react-dom": "18.3.1" + "next-mdx-remote": "^5.0.0", + "react": "catalog:react18", + "react-dom": "catalog:react18" }, "devDependencies": { - "@mdx-js/loader": "^3.1.0", - "@mdx-js/react": "^3.1.0", - "@next/mdx": "^14.2.18", + "@repo/tailwindcss-config": "workspace:^", + "@repo/typescript-config": "workspace:*", + "@storybook/react": "^8.4.7", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.0.1", "@testing-library/user-event": "^14.5.2", - "@types/mdx": "^2.0.13", - "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", + "@types/node": "^22", + "@types/react": "catalog:react18", + "@types/react-dom": "catalog:react18", "@types/ws": "^8.5.13", "@vitejs/plugin-react": "^4.3.4", - "@vitest/coverage-v8": "^2.1.6", - "@xionwcfm/tailwindcss-config": "workspace:^", - "@repo/typescript-config": "workspace:*", - "chokidar": "^3.6.0", - "happy-dom": "^14.12.3", + "@vitest/coverage-v8": "^2.1.8", + "chokidar": "^4.0.1", + "happy-dom": "^15.11.7", "markdown-wasm": "^1.2.0", - "next-mdx-remote": "^5.0.0", "npm-run-all": "^4.1.5", "postcss": "^8", "react-fast-marquee": "^1.6.5", - "rehype-autolink-headings": "^7.1.0", - "rehype-pretty-code": "^0.14.0", - "rehype-slug": "^6.0.0", - "remark-breaks": "^4.0.0", - "remark-gfm": "^4.0.0", "sharp": "^0.33.5", - "shiki": "^1.24.0", - "shikiji": "^0.10.2", "tailwindcss": "^3.4.15", "tailwindcss-animate": "^1.0.7", "typescript": "^5", - "vite": "^5.4.11", - "vite-tsconfig-paths": "^4.3.2", - "vitest": "^2.1.6", + "vite": "^6.0.2", + "vite-tsconfig-paths": "^5.1.3", + "vitest": "^2.1.8", "vitest-fetch-mock": "^0.4.2", "ws": "^8.18.0" } diff --git a/apps/blog/posts/frontend/pnpm-catalog.mdx b/apps/blog/posts/frontend/pnpm-catalog.mdx index 0edcafc..251d8af 100644 --- a/apps/blog/posts/frontend/pnpm-catalog.mdx +++ b/apps/blog/posts/frontend/pnpm-catalog.mdx @@ -160,4 +160,5 @@ catalogs는 직관적인 관리 방식을 가지고 있었고 VsCode를 사용 catalogs는 모노레포에서의 공통된 버전관리라는 문제를 잘 풀어주는 기능이라고 생각해요 아직 사용해보시지 않았다면 한번 적용해보시는 것을 매우 추천드립니다. -읽어주셔서 감사합니다. \ No newline at end of file +읽어주셔서 감사합니다. + diff --git a/apps/blog/posts/nextjs/next-forge.mdx b/apps/blog/posts/nextjs/next-forge.mdx new file mode 100644 index 0000000..699978e --- /dev/null +++ b/apps/blog/posts/nextjs/next-forge.mdx @@ -0,0 +1,11 @@ +--- +title: Next Forge 오픈소스 프로젝트에서 배우는 모노레포 패키지 전략 +description: 필요한 것만 잘 취해오는 것도 능력이 아닐까요? +thumbnail: fallback +categories: nextjs +writeDate: 2024-12-01T08:29:07.053Z +releaseDate: 2024-12-01T14:32:00.053Z +canView: true +authority: public +--- + diff --git a/apps/blog/src/entities/post/lib/utils/index.ts b/apps/blog/src/entities/post/lib/utils/index.ts deleted file mode 100644 index 6b3dbb2..0000000 --- a/apps/blog/src/entities/post/lib/utils/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ASSET_XION_THUMBNAIL_FALLBACK_336_115 } from "~/shared/assets"; - -export const getThumbnail = (param: string) => { - switch (param) { - default: - return ASSET_XION_THUMBNAIL_FALLBACK_336_115; - } -}; diff --git a/apps/blog/src/entities/post/model/post-service.test.ts b/apps/blog/src/entities/post/model/post-service.test.ts index 71b9f14..c356f8a 100644 --- a/apps/blog/src/entities/post/model/post-service.test.ts +++ b/apps/blog/src/entities/post/model/post-service.test.ts @@ -1,13 +1,12 @@ import { canViewPost } from "./post.service"; describe("canViewPost의 동작을 테스트합니다.", () => { - it("canView가 false라면 반환은 false", () => { - expect(canViewPost({ canView: false, releaseDate: "" }, new Date())).toBe(false); + it("개발환경에서는 무조건 true", () => { + expect(canViewPost({ canView: false, releaseDate: "" }, new Date())).toBe(true); }); it("canView가 true면서 releaseDate가 오늘보다 이르다면 true", () => { const date = "2024-06-20T16:00:00Z"; const today = new Date("2024-06-20T16:00:01Z"); - console.log(today.getTime() > new Date(date).getTime()); expect(canViewPost({ canView: true, releaseDate: date }, today)).toBe(true); }); }); diff --git a/apps/blog/src/entities/post/model/post.service.ts b/apps/blog/src/entities/post/model/post.service.ts index ba4b692..4ace314 100644 --- a/apps/blog/src/entities/post/model/post.service.ts +++ b/apps/blog/src/entities/post/model/post.service.ts @@ -2,16 +2,19 @@ import fs from "node:fs"; import path from "node:path"; import { safeGetIso } from "@repo/date/safe-get-iso"; import { toDate } from "@repo/date/to-date"; +import { env } from "@repo/env"; import { compileMDX } from "next-mdx-remote/rsc"; -import { ENVIRONMENT } from "~/shared/environment"; import { getKoreanToday } from "~/shared/utils/date/get-korean-today"; import type { FrontmatterType, PostType, PostWithFrontmatterType } from "./post.model"; + const POST_REPOSITORY_FOLDER_NAME = "posts"; const getPostsDirectory = () => { return path.join(process.cwd(), POST_REPOSITORY_FOLDER_NAME); }; +const MDX_REGEX = /\.mdx$/; + const readDirectory = (directory: string): Pick[] => { const postsDirectory = getPostsDirectory(); return fs.readdirSync(directory, { withFileTypes: true }).reduce[]>((posts, file) => { @@ -20,11 +23,8 @@ const readDirectory = (directory: string): Pick[] => { return posts.concat(readDirectory(fullPath)); } if (file.isFile() && path.extname(file.name) === ".mdx") { - const filePath = fullPath - .replace(postsDirectory, "") - .replace(/^\/+/, "") - .replace(/\.mdx$/, "") - .split("/"); + const relativePath = path.relative(postsDirectory, fullPath); + const filePath = relativePath.replace(MDX_REGEX, "").split("/"); posts.push({ filePath }); } return posts; @@ -45,13 +45,17 @@ const findPostFile = (directory: string, filePath: string[]): PostType | null => }; export const canViewPost = (frontmatter: Pick, today: Date) => { - if (ENVIRONMENT.NODE_ENV === "development") return true; + if (env.NODE_ENV === "development") { + return true; + } if (!frontmatter.canView) { return false; } const date = safeGetIso(frontmatter.releaseDate); - if (!date) throw new Error("invalid Post Release Date by canViewPost"); + if (!date) { + throw new Error("invalid Post Release Date by canViewPost"); + } const todayTime = getKoreanToday(today).getTime(); const dateTime = toDate(date).getTime(); const isOverReleaseDate = todayTime > dateTime; @@ -69,16 +73,20 @@ export const getFrontmatter = async (source: string): Promise = export const getPost = async (filePath: string[]): Promise => { const postsDirectory = getPostsDirectory(); const post = findPostFile(postsDirectory, filePath); - if (!post) return null; + if (!post) { + return null; + } const frontmatter = await getFrontmatter(post.content); - if (!canViewPost(frontmatter, new Date())) return null; + if (!canViewPost(frontmatter, new Date())) { + return null; + } return Object.assign(post, frontmatter); }; export const getAllPosts = async () => { const postsDirectory = getPostsDirectory(); const posts = await Promise.all(readDirectory(postsDirectory).map((path) => getPost(path.filePath))); - const validPosts = posts.filter((post) => post !== null) as Array; + const validPosts = posts.filter((post) => post !== null) as PostWithFrontmatterType[]; const canViewPosts = validPosts.filter((post) => canViewPost(post, new Date())); return canViewPosts; }; diff --git a/apps/blog/src/entities/post/ui/mdx/mdx-remote.tsx b/apps/blog/src/entities/post/ui/mdx/mdx-remote.tsx deleted file mode 100644 index 00a22cc..0000000 --- a/apps/blog/src/entities/post/ui/mdx/mdx-remote.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { Stack } from "@xionwcfm/xds"; -import { MDXRemote } from "next-mdx-remote/rsc"; -import rehypeAutolinkHeadings from "rehype-autolink-headings"; -import rehypePrettyCode from "rehype-pretty-code"; -import rehypeSlug from "rehype-slug"; -import remarkBreaks from "remark-breaks"; -import { MDXComponents } from "./mdx-components"; - -interface MdxRemoteProps { - source: string; -} -export const MdxRemote = ({ source }: MdxRemoteProps) => { - return ( - - - - ); -}; diff --git a/apps/blog/src/entities/post/ui/post/post-card.tsx b/apps/blog/src/entities/post/ui/post/PostCard.tsx similarity index 76% rename from apps/blog/src/entities/post/ui/post/post-card.tsx rename to apps/blog/src/entities/post/ui/post/PostCard.tsx index e4cc297..d310ff2 100644 --- a/apps/blog/src/entities/post/ui/post/post-card.tsx +++ b/apps/blog/src/entities/post/ui/post/PostCard.tsx @@ -2,7 +2,6 @@ import { formatDate } from "@repo/date/format-date"; import { Box, Paragraph, Stack } from "@xionwcfm/xds"; import Link from "next/link"; -import React from "react"; import { AUTHOR_NICKNAME } from "~/shared/constants"; import { ROUTES } from "~/shared/routes"; import type { PostWithFrontmatterType } from "../../model/post.model"; @@ -18,7 +17,7 @@ export const PostCard = (props: PostCardProps) => { return ( - + {post.categories} @@ -29,18 +28,18 @@ export const PostCard = (props: PostCardProps) => { size={"6"} color={"neutral-700"} className=" max-w-[336px] md:max-w-[700px] xl:max-w-[1000px]" - responsive + responsive={true} overflow={"ellipsis"} > {post.title} - + {post.description} - + {AUTHOR_NICKNAME} - + {date} diff --git a/apps/blog/src/entities/post/ui/post/post-detail-author-and-date.tsx b/apps/blog/src/entities/post/ui/post/PostDetailAuthorAndDate.tsx similarity index 100% rename from apps/blog/src/entities/post/ui/post/post-detail-author-and-date.tsx rename to apps/blog/src/entities/post/ui/post/PostDetailAuthorAndDate.tsx diff --git a/apps/blog/src/entities/post/ui/post/post-detail-author-with-char.tsx b/apps/blog/src/entities/post/ui/post/PostDetailAuthorWithChar.tsx similarity index 83% rename from apps/blog/src/entities/post/ui/post/post-detail-author-with-char.tsx rename to apps/blog/src/entities/post/ui/post/PostDetailAuthorWithChar.tsx index d1b2d0b..68160e5 100644 --- a/apps/blog/src/entities/post/ui/post/post-detail-author-with-char.tsx +++ b/apps/blog/src/entities/post/ui/post/PostDetailAuthorWithChar.tsx @@ -5,9 +5,9 @@ import { Paragraph, Stack } from "@xionwcfm/xds"; import { ASSET_XION_CHAR_GRAY } from "~/shared/assets"; import { AUTHOR_DESCRIPTION, AUTHOR_NAME } from "~/shared/constants"; import { ROUTES } from "~/shared/routes"; -import { XionEmailIcon } from "~/shared/ui/icon/xion-email-icon"; -import { XionGithubLogoIcon } from "~/shared/ui/icon/xion-github-icon"; -import { XionLinkedinIcon } from "~/shared/ui/icon/xion-linkedin-icon"; +import { XionEmailIcon } from "~/shared/ui/icon/XionEmailIcon"; +import { XionGithubLogoIcon } from "~/shared/ui/icon/XionGithubIcon"; +import { XionLinkedinIcon } from "~/shared/ui/icon/XionLinkedInIcon"; export const PostDetailAuthorWithChar = () => { return ( diff --git a/apps/blog/src/entities/post/ui/post/post-detail-title.tsx b/apps/blog/src/entities/post/ui/post/PostDetailTitle.tsx similarity index 69% rename from apps/blog/src/entities/post/ui/post/post-detail-title.tsx rename to apps/blog/src/entities/post/ui/post/PostDetailTitle.tsx index c55e850..908a224 100644 --- a/apps/blog/src/entities/post/ui/post/post-detail-title.tsx +++ b/apps/blog/src/entities/post/ui/post/PostDetailTitle.tsx @@ -3,7 +3,7 @@ import type { PropsWithChildren } from "react"; export const PostDetailTitle = (props: PropsWithChildren) => { return ( - + {props.children} ); diff --git a/apps/blog/src/page/post-detail.page.tsx b/apps/blog/src/page/PostDetailPage.tsx similarity index 72% rename from apps/blog/src/page/post-detail.page.tsx rename to apps/blog/src/page/PostDetailPage.tsx index 8797f4f..eab18ab 100644 --- a/apps/blog/src/page/post-detail.page.tsx +++ b/apps/blog/src/page/PostDetailPage.tsx @@ -1,11 +1,12 @@ +import { MdxRemote } from "@repo/mdx"; import { Box, Spacing, Stack } from "@xionwcfm/xds"; import { Chip } from "@xionwcfm/xds/chip"; import type { PostWithFrontmatterType } from "~/entities/post/model/post.model"; -import { MdxRemote } from "~/entities/post/ui/mdx/mdx-remote"; -import { PostDetailAuthorAndDate } from "~/entities/post/ui/post/post-detail-author-and-date"; -import { PostDetailAuthorWithChar } from "~/entities/post/ui/post/post-detail-author-with-char"; -import { PostDetailTitle } from "~/entities/post/ui/post/post-detail-title"; -import { Separate } from "~/shared/ui/common/separate"; +import { PostDetailAuthorAndDate } from "~/entities/post/ui/post/PostDetailAuthorAndDate"; +import { PostDetailAuthorWithChar } from "~/entities/post/ui/post/PostDetailAuthorWithChar"; +import { PostDetailTitle } from "~/entities/post/ui/post/PostDetailTitle"; +import { Separate } from "~/shared/ui/common/Separate"; + type PostPageProps = { post: PostWithFrontmatterType; }; @@ -23,13 +24,13 @@ export default function PostDetailPage({ post }: PostPageProps) { - + - + ); } diff --git a/apps/blog/src/shared/environment/index.ts b/apps/blog/src/shared/environment/index.ts deleted file mode 100644 index df5b900..0000000 --- a/apps/blog/src/shared/environment/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const ENVIRONMENT = { - NODE_ENV: process.env.NODE_ENV, - GA_ID: process.env.NEXT_PUBLIC_GA_ID as string, - GTM_ID: process.env.NEXT_PUBLIC_GTM_ID as string, - GSC_ID: process.env.NEXT_PUBLIC_GSC_ID as string, -}; diff --git a/apps/blog/src/shared/feature-flag/index.ts b/apps/blog/src/shared/feature-flag/index.ts index 4d32c7a..919c793 100644 --- a/apps/blog/src/shared/feature-flag/index.ts +++ b/apps/blog/src/shared/feature-flag/index.ts @@ -1,5 +1,4 @@ -import { ENVIRONMENT } from "../environment"; - +import { env } from "@repo/env"; type FeatureFlagType = "header-hambuger" | "author-email"; type FeatureFlagContextType = { @@ -7,10 +6,10 @@ type FeatureFlagContextType = { }; export const isEnabled = (type: FeatureFlagType, context?: FeatureFlagContextType) => { - const today = context?.today ?? new Date(); + const _today = context?.today ?? new Date(); switch (type) { case "header-hambuger": - return ENVIRONMENT.NODE_ENV === "development"; + return env.NODE_ENV === "development"; case "author-email": return true; default: diff --git a/apps/blog/src/shared/routes/index.ts b/apps/blog/src/shared/routes/index.ts index 5551be9..23d5244 100644 --- a/apps/blog/src/shared/routes/index.ts +++ b/apps/blog/src/shared/routes/index.ts @@ -5,6 +5,7 @@ const createBaseUrl = (path: string, context?: RoutesContextType) => { return `${baseurl}${path}`; }; type RoutesContextType = { withBaseUrl?: boolean }; + export const ROUTES = { root: () => "/", postDetail: (postsPath: string[], context?: RoutesContextType) => diff --git a/apps/blog/src/shared/ui/common/main-xion-wcfm.tsx b/apps/blog/src/shared/ui/common/MainXionWCFM.tsx similarity index 72% rename from apps/blog/src/shared/ui/common/main-xion-wcfm.tsx rename to apps/blog/src/shared/ui/common/MainXionWCFM.tsx index 510c0b5..d90cc66 100644 --- a/apps/blog/src/shared/ui/common/main-xion-wcfm.tsx +++ b/apps/blog/src/shared/ui/common/MainXionWCFM.tsx @@ -2,14 +2,14 @@ import { Image } from "@repo/router/image"; import { Paragraph, Stack } from "@xionwcfm/xds"; import { ASSET_XION_CHAR_WHITE } from "~/shared/assets"; -import { XionEmailIcon } from "../icon/xion-email-icon"; -import { XionGithubLogoIcon } from "../icon/xion-github-icon"; -import { XionLinkedinIcon } from "../icon/xion-linkedin-icon"; +import { XionEmailIcon } from "../icon/XionEmailIcon"; +import { XionGithubLogoIcon } from "../icon/XionGithubIcon"; +import { XionLinkedinIcon } from "../icon/XionLinkedInIcon"; -export const MainXionWCFM = () => { +export const MainXionWcfm = () => { return ( - + {"FRONTEND DEVELOPER\nXIONWCFM"} diff --git a/apps/blog/src/shared/ui/common/MainXionWcfm.stories.tsx b/apps/blog/src/shared/ui/common/MainXionWcfm.stories.tsx new file mode 100644 index 0000000..bade519 --- /dev/null +++ b/apps/blog/src/shared/ui/common/MainXionWcfm.stories.tsx @@ -0,0 +1,15 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { MainXionWcfm } from "./MainXionWcfm"; + +const meta = { + title: "Blog/Main", + component: MainXionWcfm, + parameters: { + layout: "fullscreen", + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LoggedOut: Story = {}; diff --git a/apps/blog/src/shared/ui/icon/xion-email-icon.tsx b/apps/blog/src/shared/ui/icon/XionEmailIcon.tsx similarity index 100% rename from apps/blog/src/shared/ui/icon/xion-email-icon.tsx rename to apps/blog/src/shared/ui/icon/XionEmailIcon.tsx diff --git a/apps/blog/src/shared/ui/icon/xion-github-icon.tsx b/apps/blog/src/shared/ui/icon/XionGithubIcon.tsx similarity index 100% rename from apps/blog/src/shared/ui/icon/xion-github-icon.tsx rename to apps/blog/src/shared/ui/icon/XionGithubIcon.tsx diff --git a/apps/blog/src/shared/ui/icon/xion-linkedin-icon.tsx b/apps/blog/src/shared/ui/icon/XionLinkedInIcon.tsx similarity index 100% rename from apps/blog/src/shared/ui/icon/xion-linkedin-icon.tsx rename to apps/blog/src/shared/ui/icon/XionLinkedInIcon.tsx diff --git a/apps/blog/src/shared/ui/iframe.tsx b/apps/blog/src/shared/ui/iframe.tsx deleted file mode 100644 index 1269b94..0000000 --- a/apps/blog/src/shared/ui/iframe.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { cn } from "@xionwcfm/xds"; -import { ComponentPropsWithoutRef } from "react"; - -const MOBILE_SIZE = { - IPHONE_14_PRO_MAX: { - width: "430px", - height: "932px", - }, -}; - -type MobieSizeVariants = keyof typeof MOBILE_SIZE; - -export const Iframe = (props: ComponentPropsWithoutRef<"iframe"> & { title: string; device?: MobieSizeVariants }) => { - const { children, className, title, src, device = "IPHONE_14_PRO_MAX", ...rest } = props; - - return ( -