├── .github ├── CODEOWNERS ├── dependabot.yml └── images │ └── cover-transparent-with-1chooo-com.png ├── .gitignore ├── .prettierignore ├── .vscode ├── extensions.json └── launch.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── apps ├── cli │ ├── .editorconfig │ ├── .github │ │ └── workflows │ │ │ └── release.yml │ ├── .gitignore │ ├── .husky │ │ ├── commit-msg │ │ └── pre-commit │ ├── .npmignore │ ├── .releaserc.json │ ├── README.md │ ├── bin │ │ ├── run │ │ └── run.ts │ ├── commitlint.config.js │ ├── eslint.config.js │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ └── commands.test.ts │ │ ├── commands │ │ │ ├── create.ts │ │ │ ├── greeting.ts │ │ │ ├── index.ts │ │ │ └── info.ts │ │ ├── index.ts │ │ └── logger.ts │ ├── tsconfig.json │ ├── tsup.config.ts │ └── vitest.config.ts ├── docs │ ├── .github │ │ └── screenshot.png │ ├── .gitignore │ ├── LICENSE │ ├── eslint.config.js │ ├── next-env.d.ts │ ├── next.config.mjs │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── images │ │ │ ├── cover-transparent-with-1chooo-com.png │ │ │ ├── cover-transparent.png │ │ │ ├── cover-with-1chooo-com.png │ │ │ ├── cover.png │ │ │ ├── seo.webp │ │ │ └── wiki │ │ │ │ └── blog-before.png │ │ ├── logo192.png │ │ └── logo512.png │ ├── src │ │ ├── app │ │ │ ├── [[...mdxPath]] │ │ │ │ └── page.tsx │ │ │ └── layout.tsx │ │ ├── content │ │ │ ├── _meta.ts │ │ │ ├── acknowledgments.mdx │ │ │ ├── api.md │ │ │ ├── api.mdx │ │ │ ├── change-log.mdx │ │ │ ├── code-walkthrough.mdx │ │ │ ├── contributing.mdx │ │ │ ├── features.mdx │ │ │ ├── index.mdx │ │ │ ├── stack.mdx │ │ │ ├── terms.mdx │ │ │ ├── user-guide.mdx │ │ │ └── wiki.mdx │ │ └── mdx-components.ts │ └── tsconfig.json └── web │ ├── .env.example │ ├── .gitignore │ ├── components.json │ ├── eslint.config.js │ ├── mdx-components.tsx │ ├── next-env.d.ts │ ├── next.config.ts │ ├── package.json │ ├── postcss.config.cjs │ ├── public │ ├── cv.pdf │ ├── images │ │ ├── banner │ │ │ ├── posts │ │ │ │ ├── 0001-two-sum.webp │ │ │ │ ├── 1052-grumpy-bookstore-owner.webp │ │ │ │ ├── 1382-balance-a-binary-search-tree.webp │ │ │ │ ├── 1480-running-sum-of-1d-array.webp │ │ │ │ ├── 1550-three-consecutive-odds.webp │ │ │ │ ├── 1791-find-center-of-star-graph.webp │ │ │ │ ├── 2181-merge-nodes-in-between-zeros.webp │ │ │ │ ├── 500-commits-milestone-in-1chooo-com.webp │ │ │ │ ├── amazon-linux-2-install-docker.webp │ │ │ │ ├── give-your-github-repos-a-makeover-with-vscodes-material-icons.webp │ │ │ │ ├── goodbye-react-create-app.webp │ │ │ │ ├── how-to-add-linear-gradient-effect-to-text.webp │ │ │ │ ├── how-to-enable-word-wrap-mdx-files-in-vscode.webp │ │ │ │ ├── hugo-s-go-to-stack-for-building-maintainable-software.webp │ │ │ │ ├── leetcode-november-2024-daily-challenge.webp │ │ │ │ ├── mac-install-nodejs-npm.webp │ │ │ │ ├── make-your-react-more-elegant-with-map.webp │ │ │ │ ├── make-your-titles-more-readable-react-wrap-balancer.webp │ │ │ │ ├── move-shared-components-to-global-layout.webp │ │ │ │ ├── say-goodbye-to-git-graph-in-vscode.webp │ │ │ │ ├── three-methods-to-access-environment-variable-values-in-python.png │ │ │ │ ├── unknown-at-rule-tailwind-in-vscode.png │ │ │ │ └── who-is-chun-ho-hugo-lin.webp │ │ │ └── projects │ │ │ │ ├── 1chooo-com.webp │ │ │ │ ├── anon-chat.webp │ │ │ │ ├── aws-edu-101.webp │ │ │ │ ├── evolving-beasts.webp │ │ │ │ ├── game-scope.webp │ │ │ │ ├── gym-route.webp │ │ │ │ ├── hua-tank.webp │ │ │ │ ├── ncufresh.webp │ │ │ │ ├── refinaid.webp │ │ │ │ ├── thermal-calculator.webp │ │ │ │ ├── todam-tw.webp │ │ │ │ └── uml-editor.webp │ │ ├── blog │ │ │ ├── chun-ho-hugo-lin │ │ │ │ └── banner.webp │ │ │ ├── hugos-stack-standards │ │ │ │ └── banner.webp │ │ │ ├── placeholder.webp │ │ │ └── python-env │ │ │ │ └── banner.webp │ │ ├── logo │ │ │ ├── aws.svg │ │ │ ├── ecv.svg │ │ │ ├── futurenest.svg │ │ │ ├── ncu.svg │ │ │ ├── pegatron.svg │ │ │ └── usc.svg │ │ ├── opengraph-image.png │ │ ├── posts │ │ │ ├── 500-commits-milestone-in-1chooo-com │ │ │ │ ├── 500-commit-achieving.png │ │ │ │ ├── about.png │ │ │ │ ├── blog.png │ │ │ │ ├── contact.png │ │ │ │ ├── dependabot.png │ │ │ │ ├── ga.png │ │ │ │ ├── milestone.png │ │ │ │ ├── portfolio.png │ │ │ │ ├── readme.png │ │ │ │ ├── resume.png │ │ │ │ ├── tag.png │ │ │ │ ├── tests.png │ │ │ │ └── well-commits.png │ │ │ ├── cover.png │ │ │ ├── git-commit-message.png │ │ │ ├── git_tips.png │ │ │ ├── give-your-github-repos-a-makeover-with-vscodes-material-icons │ │ │ │ ├── add-to-your-chrmoe-based-browser.png │ │ │ │ ├── before.png │ │ │ │ ├── final.png │ │ │ │ ├── my-settings.png │ │ │ │ └── several-choices.png │ │ │ ├── goodbye-react-create-app │ │ │ │ ├── create-react-app-v-5-0-1.png │ │ │ │ └── start-a-new-react-project.png │ │ │ ├── how-to-add-linear-gradient-effect-to-text │ │ │ │ ├── after.png │ │ │ │ ├── before.png │ │ │ │ ├── final.png │ │ │ │ ├── linear-gradient-in-next-js-site.png │ │ │ │ └── selection-not-work.png │ │ │ ├── how-to-enable-word-wrap-mdx-files-in-vscode │ │ │ │ ├── after.png │ │ │ │ ├── before.png │ │ │ │ ├── how-to-enable-word-wrap-mdx-files-in-vscode.png │ │ │ │ └── toogle-word-wrap.png │ │ │ ├── make-your-titles-more-readable-react-wrap-balancer │ │ │ │ ├── demo-01.png │ │ │ │ └── demo-02.png │ │ │ ├── no_ads.png │ │ │ ├── nuphy_unboxing.png │ │ │ ├── react_mapping_tips.png │ │ │ ├── say-goodbye-to-git-graph-in-vscode │ │ │ │ ├── commit-details-in-git-graph.png │ │ │ │ ├── git-graph-in-vscode.png │ │ │ │ ├── git-graph.png │ │ │ │ └── say-goodbye-to-git-graph-in-vscode.png │ │ │ ├── unknown-at-rule-tailwind-in-vscode │ │ │ │ ├── no-tailwind-alert-message.png │ │ │ │ ├── search-postcss-language-support.png │ │ │ │ └── unknown-tailwind-message.png │ │ │ └── who-is-chun-ho-hugo-lin │ │ │ │ ├── postspark-1chooo-github-contributions-2024.png │ │ │ │ └── postspark-1chooo-github-contributions.png │ │ ├── profile.webp │ │ └── project │ │ │ ├── 1chooo-com │ │ │ └── banner.webp │ │ │ ├── anon-chat │ │ │ └── banner.webp │ │ │ ├── jian-theme │ │ │ └── banner.png │ │ │ ├── todam-tw │ │ │ └── banner.webp │ │ │ ├── tools │ │ │ └── banner.webp │ │ │ └── uml-editor │ │ │ └── banner.webp │ └── manifest.json │ ├── scripts │ └── 001-create-views-table.sql │ ├── src │ ├── __tests__ │ │ └── types │ │ │ ├── nav-bar.test.ts │ │ │ ├── post.test.ts │ │ │ └── resume.test.ts │ ├── app │ │ ├── (home) │ │ │ ├── (cookbook) │ │ │ │ ├── design │ │ │ │ │ └── page.mdx │ │ │ │ ├── layout.tsx │ │ │ │ └── md │ │ │ │ │ └── page.mdx │ │ │ ├── (exp) │ │ │ │ ├── bookmarks │ │ │ │ │ ├── loading.tsx │ │ │ │ │ └── page.tsx │ │ │ │ ├── markdown-alerts │ │ │ │ │ └── page.tsx │ │ │ │ ├── mdx │ │ │ │ │ └── page.mdx │ │ │ │ ├── og-image-generator │ │ │ │ │ ├── og-image-generator.tsx │ │ │ │ │ └── page.tsx │ │ │ │ ├── react-scroll-motion │ │ │ │ │ └── page.tsx │ │ │ │ ├── tag-selection-interaction │ │ │ │ │ └── page.tsx │ │ │ │ └── web-vitals-dashboard │ │ │ │ │ └── page.tsx │ │ │ ├── (metadata) │ │ │ │ ├── llms-full.txt │ │ │ │ │ └── route.ts │ │ │ │ ├── llms.txt │ │ │ │ │ └── route.ts │ │ │ │ └── rss.xml │ │ │ │ │ └── route.ts │ │ │ ├── [...rest] │ │ │ │ └── page.tsx │ │ │ ├── blog │ │ │ │ ├── [slug] │ │ │ │ │ └── page.tsx │ │ │ │ ├── category │ │ │ │ │ └── [category] │ │ │ │ │ │ └── page.tsx │ │ │ │ ├── page.tsx │ │ │ │ └── view-counter.tsx │ │ │ ├── code-of-conduct │ │ │ │ └── page.tsx │ │ │ ├── contact │ │ │ │ └── page.tsx │ │ │ ├── gallery │ │ │ │ └── page.tsx │ │ │ ├── layout.tsx │ │ │ ├── not-found.tsx │ │ │ ├── page.tsx │ │ │ ├── project │ │ │ │ ├── [slug] │ │ │ │ │ └── page.tsx │ │ │ │ ├── category │ │ │ │ │ └── [category] │ │ │ │ │ │ └── page.tsx │ │ │ │ ├── page.tsx │ │ │ │ └── view-counter.tsx │ │ │ ├── resume │ │ │ │ └── page.tsx │ │ │ └── terms │ │ │ │ └── page.tsx │ │ ├── api │ │ │ ├── github │ │ │ │ ├── repos │ │ │ │ │ └── route.ts │ │ │ │ └── users │ │ │ │ │ └── route.ts │ │ │ └── views │ │ │ │ ├── blog │ │ │ │ └── route.ts │ │ │ │ └── project │ │ │ │ └── route.ts │ │ ├── favicon.ico │ │ ├── globals.css │ │ ├── layout.tsx │ │ ├── og │ │ │ └── route.tsx │ │ ├── opengraph-image.tsx │ │ ├── robots.ts │ │ ├── sitemap.ts │ │ └── twitter-image.tsx │ ├── components │ │ ├── about │ │ │ ├── auto-rotate-globe.tsx │ │ │ ├── coding-stats.tsx │ │ │ ├── globe.tsx │ │ │ ├── life-styles.tsx │ │ │ ├── marquee.tsx │ │ │ ├── my-writings.tsx │ │ │ ├── posts-loop.tsx │ │ │ ├── see-more-button.tsx │ │ │ ├── selected-projects.tsx │ │ │ └── talk-to-hugo.tsx │ │ ├── analytics │ │ │ ├── analytics.tsx │ │ │ ├── google.tsx │ │ │ ├── index.tsx │ │ │ ├── umami.tsx │ │ │ ├── vercel.tsx │ │ │ └── web-vitals.tsx │ │ ├── animations │ │ │ ├── animated-section.tsx │ │ │ ├── animations.tsx │ │ │ ├── fade-up.tsx │ │ │ └── staggered-animation-section.tsx │ │ ├── comments.tsx │ │ ├── filter │ │ │ ├── filter-list.tsx │ │ │ └── filter-select-box.tsx │ │ ├── gradient-card.tsx │ │ ├── hello.tsx │ │ ├── icon-box.tsx │ │ ├── icons.tsx │ │ ├── layout │ │ │ ├── footer.tsx │ │ │ ├── home-header.tsx │ │ │ ├── nav-bar.tsx │ │ │ ├── sidebar.tsx │ │ │ └── vercel-navbar-more.tsx │ │ ├── loading.tsx │ │ ├── magicui │ │ │ ├── animated-gradient-text-demo.tsx │ │ │ ├── animated-gradient-text.tsx │ │ │ ├── animated-shiny-text.tsx │ │ │ ├── blur-fade-demo.tsx │ │ │ ├── blur-fade.tsx │ │ │ ├── marquee-demo.tsx │ │ │ └── marquee.tsx │ │ ├── markdown-alert.tsx │ │ ├── markdown │ │ │ ├── anchor-header.tsx │ │ │ ├── anchor.tsx │ │ │ ├── block-quote.tsx │ │ │ ├── code-block.tsx │ │ │ ├── markdown-image.tsx │ │ │ └── paragraph.tsx │ │ ├── mdx │ │ │ ├── anchor.tsx │ │ │ ├── blockquote.tsx │ │ │ ├── callout.tsx │ │ │ ├── code-block.tsx │ │ │ ├── copy-button.tsx │ │ │ ├── github-map.tsx │ │ │ ├── heading.tsx │ │ │ ├── image.tsx │ │ │ ├── index.tsx │ │ │ ├── list-item.tsx │ │ │ ├── ordered-list.tsx │ │ │ ├── paragraph.tsx │ │ │ ├── separator.tsx │ │ │ ├── tech-badge.tsx │ │ │ └── unordered-list.tsx │ │ ├── meta │ │ │ └── twitter-card-meta.tsx │ │ ├── page-title.tsx │ │ ├── pagination.tsx │ │ ├── progress-bar.tsx │ │ ├── project │ │ │ └── project-links.tsx │ │ ├── react-scroll-motion │ │ │ ├── Animator.tsx │ │ │ ├── ScrollContainer.tsx │ │ │ ├── ScrollPage.tsx │ │ │ ├── animations │ │ │ │ ├── AnimationTool.ts │ │ │ │ ├── FadeAnimation.ts │ │ │ │ ├── MoveAnimation.ts │ │ │ │ ├── StickyAnimation.ts │ │ │ │ ├── ZoomAnimation.ts │ │ │ │ └── index.ts │ │ │ ├── constants │ │ │ │ ├── index.ts │ │ │ │ ├── initialScrollData.ts │ │ │ │ └── initialScrollPage.ts │ │ │ ├── index.ts │ │ │ ├── stores │ │ │ │ ├── ScrollDataContext.ts │ │ │ │ ├── ScrollPageContext.ts │ │ │ │ └── index.ts │ │ │ ├── types │ │ │ │ ├── Animation.ts │ │ │ │ ├── ScrollData.ts │ │ │ │ ├── ScrollPage.ts │ │ │ │ ├── Style.ts │ │ │ │ └── index.ts │ │ │ └── utils │ │ │ │ ├── computeStyle.ts │ │ │ │ ├── environment.ts │ │ │ │ ├── index.ts │ │ │ │ └── interpolation.ts │ │ ├── reddit-embed.tsx │ │ ├── resume │ │ │ ├── resume-card.tsx │ │ │ └── skills-bar.tsx │ │ ├── section │ │ │ ├── about.tsx │ │ │ └── resume-timeline.tsx │ │ ├── svg-icons.tsx │ │ ├── tech-badge.tsx │ │ ├── testimonials.tsx │ │ ├── third-party-script-embed.tsx │ │ └── tweet.tsx │ ├── config │ │ └── index.ts │ ├── content │ │ ├── blog │ │ │ ├── hugos-stack-standards.mdx │ │ │ ├── python-env.mdx │ │ │ ├── software-compound-interest.mdx │ │ │ └── who-is-chun-ho-hugo-lin.mdx │ │ ├── page │ │ │ ├── about.mdx │ │ │ ├── code-of-conduct.mdx │ │ │ └── terms.mdx │ │ └── project │ │ │ ├── 1chooo-com.mdx │ │ │ ├── anon-chat.mdx │ │ │ ├── jian-theme.mdx │ │ │ ├── todam-tw.mdx │ │ │ ├── tools.mdx │ │ │ └── uml-editor.mdx │ ├── lib │ │ ├── api │ │ │ └── mdx.ts │ │ ├── constants.ts │ │ ├── markdown-parser │ │ │ ├── index.ts │ │ │ ├── parse-blockquote.tsx │ │ │ ├── parse-bold.ts │ │ │ ├── parse-headings.tsx │ │ │ ├── parse-highlight.ts │ │ │ ├── parse-horizontal-rule.tsx │ │ │ ├── parse-image.ts │ │ │ ├── parse-inline-code.ts │ │ │ ├── parse-italic.ts │ │ │ ├── parse-links.ts │ │ │ ├── parse-markdowm.tsx │ │ │ ├── parse-strikethrough.ts │ │ │ └── parse-unordered-list.ts │ │ ├── markdown-to-html.ts │ │ ├── range.ts │ │ ├── reading-time.ts │ │ ├── rehype │ │ │ └── image-captions.ts │ │ ├── remark │ │ │ └── reading-time.ts │ │ ├── schemas │ │ │ └── page-views.ts │ │ ├── slugify │ │ │ ├── data.ts │ │ │ └── index.ts │ │ ├── supabase.ts │ │ └── tech-badge │ │ │ ├── config.ts │ │ │ └── utils.tsx │ ├── styles │ │ ├── about-section.module.css │ │ ├── about │ │ │ ├── coding-stats.css │ │ │ └── selected-projects.module.css │ │ ├── blog.module.css │ │ ├── blog │ │ │ └── blog-text.css │ │ ├── contact │ │ │ └── map-box.css │ │ ├── gradient-card.module.css │ │ ├── icon-box.module.css │ │ ├── layout │ │ │ ├── footer.css │ │ │ └── sidebar.module.css │ │ ├── markdown-styles.css │ │ ├── md.module.css │ │ ├── md │ │ │ ├── anchor.module.css │ │ │ ├── blockquote.module.css │ │ │ ├── github-map.module.css │ │ │ ├── image.module.css │ │ │ ├── list.module.css │ │ │ └── paragraph.module.css │ │ ├── nav-bar.css │ │ ├── page-title.module.css │ │ ├── preview.css │ │ ├── project.module.css │ │ ├── project │ │ │ └── project-links.module.css │ │ ├── resume │ │ │ ├── resume-card.module.css │ │ │ └── timeline.module.css │ │ ├── skills-bar.module.css │ │ ├── testimonials.css │ │ └── tweet.css │ └── types │ │ ├── about.ts │ │ ├── config.ts │ │ ├── nav-bar.ts │ │ ├── post.ts │ │ ├── react-icons │ │ ├── icon-base.tsx │ │ └── icon-context.tsx │ │ ├── resume.ts │ │ ├── rss.ts │ │ ├── slugify.ts │ │ ├── socail-media.ts │ │ └── type-guards.ts │ ├── tailwind.config.ts │ ├── tsconfig.json │ └── vitest.config.ts ├── package.json ├── packages ├── activity-calendar │ ├── LICENSE │ ├── eslint.config.js │ ├── package.json │ ├── src │ │ ├── components │ │ │ └── activity-calendar.tsx │ │ ├── constants.ts │ │ ├── hooks │ │ │ ├── use-color-scheme.ts │ │ │ ├── use-loading-animation.ts │ │ │ └── use-prefers-reduced-motion.ts │ │ ├── index.tsx │ │ ├── lib │ │ │ ├── calendar.ts │ │ │ ├── label.ts │ │ │ └── theme.ts │ │ ├── styles.ts │ │ └── types.ts │ └── tsconfig.json ├── eslint-config │ ├── README.md │ ├── base.js │ ├── next.js │ ├── package.json │ └── react-internal.js ├── github-calendar │ ├── LICENSE │ ├── eslint.config.js │ ├── package.json │ ├── src │ │ ├── index.tsx │ │ ├── lib.ts │ │ └── types.ts │ └── tsconfig.json ├── schema │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── json-ld.ts │ └── tsconfig.json ├── typescript-config │ ├── README.md │ ├── base.json │ ├── nextjs.json │ ├── package.json │ └── react-library.json └── ui │ ├── components.json │ ├── eslint.config.js │ ├── package.json │ ├── postcss.config.mjs │ ├── src │ ├── card-3d │ │ ├── v0 │ │ │ └── card-3d.tsx │ │ └── v1 │ │ │ └── card-3d.tsx │ ├── components │ │ ├── .gitkeep │ │ ├── avatar.tsx │ │ ├── badge.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── input.tsx │ │ ├── label.tsx │ │ ├── scroll-area.tsx │ │ ├── tabs.tsx │ │ └── textarea.tsx │ ├── hooks │ │ └── .gitkeep │ ├── lib │ │ └── utils.ts │ ├── portfolio-canvas.tsx │ └── styles │ │ └── globals.css │ ├── tsconfig.json │ └── tsconfig.lint.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── prettier.config.js ├── scripts ├── gen-config.js └── upgrade-version.js ├── tsconfig.json └── turbo.json /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # 1chooo.com Codeowners 2 | 3 | /* @1chooo 4 | 5 | -------------------------------------------------------------------------------- /.github/images/cover-transparent-with-1chooo-com.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/.github/images/cover-transparent-with-1chooo-com.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | drafts/ 4 | 5 | # Dependencies 6 | node_modules 7 | .pnp 8 | .pnp.js 9 | 10 | # Local env files 11 | .env 12 | .env.local 13 | .env.development.local 14 | .env.test.local 15 | .env.production.local 16 | 17 | # Testing 18 | coverage 19 | 20 | # Turbo 21 | .turbo 22 | 23 | # Vercel 24 | .vercel 25 | 26 | # Build Outputs 27 | .next/ 28 | out/ 29 | build 30 | dist 31 | 32 | 33 | # Debug 34 | npm-debug.log* 35 | yarn-debug.log* 36 | yarn-error.log* 37 | 38 | # Misc 39 | .DS_Store 40 | *.pem 41 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | *.local 5 | node_modules/* 6 | dist 7 | coverage 8 | pnpm-lock.yaml 9 | routeTree.gen.ts 10 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode", "unifiedjs.vscode-mdx"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "command": "./node_modules/.bin/astro dev", 6 | "name": "Development server", 7 | "request": "launch", 8 | "type": "node-terminal" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /apps/cli/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | 7 | [*.{js,py,md}] 8 | charset = utf-8 9 | indent_style = space 10 | indent_size = 2 -------------------------------------------------------------------------------- /apps/cli/.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | branches: 5 | - main 6 | 7 | permissions: 8 | contents: read # for checkout 9 | 10 | jobs: 11 | release: 12 | name: Release 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: write # to be able to publish a GitHub release 16 | issues: write # to be able to comment on released issues 17 | pull-requests: write # to be able to comment on released pull requests 18 | id-token: write # to enable use of OIDC for npm provenance 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v4 22 | with: 23 | fetch-depth: 0 24 | 25 | - name: Setup Node.js 26 | uses: actions/setup-node@v4 27 | with: 28 | node-version: 'lts/*' 29 | 30 | - name: Install pnpm 31 | run: npm i pnpm -g 32 | 33 | - name: Install dependencies 34 | run: pnpm install 35 | 36 | - name: Verify the integrity of provenance attestations and registry signatures for installed dependencies 37 | run: pnpm audit signatures 38 | 39 | - name: Lint 40 | run: pnpm lint 41 | 42 | - name: Test 43 | run: pnpm test 44 | 45 | - name: Build 46 | run: pnpm build 47 | 48 | - name: Release 49 | env: 50 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 51 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 52 | run: pnpm release 53 | -------------------------------------------------------------------------------- /apps/cli/.husky/commit-msg: -------------------------------------------------------------------------------- 1 | pnpm commitlint ${1} 2 | -------------------------------------------------------------------------------- /apps/cli/.husky/pre-commit: -------------------------------------------------------------------------------- 1 | pnpm lint:fix 2 | pnpm format:fix 3 | pnpm test 4 | pnpm build 5 | -------------------------------------------------------------------------------- /apps/cli/.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | tsconfig.json 3 | .prettierrc 4 | .eslintignore 5 | .eslint.cjs 6 | .env.example 7 | .releaserc.json 8 | commitlint.config.js 9 | vitest.config.ts 10 | tsup.config.ts 11 | coverage 12 | .idea 13 | .editorconfig 14 | .fleet 15 | -------------------------------------------------------------------------------- /apps/cli/.releaserc.json: -------------------------------------------------------------------------------- 1 | { 2 | "branches": [ 3 | "+([0-9])?(.{+([0-9]),x}).x", 4 | "main", 5 | "next", 6 | "next-major", 7 | { 8 | "name": "beta", 9 | "prerelease": true 10 | }, 11 | { 12 | "name": "alpha", 13 | "prerelease": true 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /apps/cli/bin/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('../dist/run') 4 | -------------------------------------------------------------------------------- /apps/cli/bin/run.ts: -------------------------------------------------------------------------------- 1 | import yargs, { CommandModule } from "yargs"; 2 | import { config } from "dotenv"; 3 | import { commands } from "@/commands"; 4 | import { bgBlue, bold, red } from "picocolors"; 5 | 6 | config(); 7 | 8 | const run = yargs(process.argv.slice(2)); 9 | 10 | run.usage( 11 | bgBlue( 12 | `Welcome to the CLI application powered by ${bold(red("cli-typescript-starter"))}! 13 | See more on https://github.com/kucherenko/cli-typescript-starter`, 14 | ), 15 | ); 16 | 17 | for (const command of commands) { 18 | run.command(command as CommandModule); 19 | } 20 | 21 | run.demandCommand(1, "You need at least one command before moving on").help() 22 | .argv; 23 | -------------------------------------------------------------------------------- /apps/cli/commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { extends: ["@commitlint/config-conventional"] }; 2 | -------------------------------------------------------------------------------- /apps/cli/eslint.config.js: -------------------------------------------------------------------------------- 1 | import { nextJsConfig } from "@1chooo/eslint-config/next-js"; 2 | 3 | /** @type {import("eslint").Linter.Config} */ 4 | export default nextJsConfig; 5 | -------------------------------------------------------------------------------- /apps/cli/src/__tests__/commands.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from "vitest"; 2 | 3 | describe("First Test Case", () => { 4 | it("should pass", () => { 5 | expect(true).toBeTruthy(); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /apps/cli/src/commands/greeting.ts: -------------------------------------------------------------------------------- 1 | import { Argv } from "yargs"; 2 | import { logger } from "@/logger"; 3 | import { bold, green } from "picocolors"; 4 | 5 | // Use 'object' to represent any non-nullish object type 6 | type GreetingArgv = object; 7 | 8 | export const command = "greeting"; 9 | export const describe = 10 | "Displays interactive prompts to demonstrate user input handling."; 11 | export const aliases = ["g"]; 12 | 13 | export function builder(yargs: Argv): Argv { 14 | return yargs; 15 | } 16 | 17 | export async function handler() { 18 | const username = await logger.prompt("What is your name?", { 19 | type: "text", 20 | }); 21 | 22 | logger.log(`Hello, ${green(bold(username))}!`); 23 | 24 | const mood = await logger.prompt("How are you?", { 25 | type: "select", 26 | options: [ 27 | "👌", 28 | "👍", 29 | "👎", 30 | { 31 | label: "🤬", 32 | value: "🤬", 33 | hint: "take care", 34 | }, 35 | ], 36 | }); 37 | logger.log(`${green(bold(username))} ${mood}, Ciao!`); 38 | } 39 | -------------------------------------------------------------------------------- /apps/cli/src/commands/index.ts: -------------------------------------------------------------------------------- 1 | import * as info from "@/commands/info"; 2 | import * as greeting from "@/commands/greeting"; 3 | import * as create from "@/commands/create"; 4 | 5 | export const commands = [info, greeting, create]; 6 | -------------------------------------------------------------------------------- /apps/cli/src/commands/info.ts: -------------------------------------------------------------------------------- 1 | import { ArgumentsCamelCase, Argv } from "yargs"; 2 | import { logger } from "@/logger"; 3 | import * as process from "node:process"; 4 | import { blue, bold, gray, green, red, yellow } from "picocolors"; 5 | 6 | interface InfoArgv { 7 | full?: boolean; 8 | } 9 | 10 | export const command = "info"; 11 | export const describe = 12 | "Basic command to display information about the CLI application."; 13 | export const aliases = ["i"]; 14 | 15 | export function builder(yargs: Argv): Argv { 16 | return yargs.option("full", { 17 | type: "boolean", 18 | alias: "f", 19 | default: true, 20 | }); 21 | } 22 | 23 | export async function handler(argv: ArgumentsCamelCase) { 24 | logger.info( 25 | bold( 26 | red("Basic command to display information about the CLI application."), 27 | ), 28 | ); 29 | logger.info(green("Node:"), bold(process.version)); 30 | logger.info(yellow("Processor architecture:"), process.arch); 31 | logger.info(blue("Current dir:"), process.cwd()); 32 | logger.info(gray("Memory usage:"), process.memoryUsage()); 33 | logger.info(gray("Argv:"), argv); 34 | if (argv.full) { 35 | logger.box(gray(bold("Process config:")), process.config); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /apps/cli/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "@/commands"; 2 | -------------------------------------------------------------------------------- /apps/cli/src/logger.ts: -------------------------------------------------------------------------------- 1 | import { createConsola } from "consola"; 2 | 3 | export const logger = createConsola({}); 4 | -------------------------------------------------------------------------------- /apps/cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@1chooo/typescript-config/nextjs.json", 3 | "compilerOptions": { 4 | "outDir": "dist/src", 5 | "baseUrl": ".", 6 | "paths": { 7 | "@/*": ["./src/*"] 8 | }, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "allowUnusedLabels": false, 12 | "allowUnreachableCode": false, 13 | "noFallthroughCasesInSwitch": true, 14 | "noUncheckedIndexedAccess": true, 15 | "noUnusedLocals": true, 16 | "noUnusedParameters": true, 17 | "forceConsistentCasingInFileNames": true, 18 | "declaration": true, 19 | "sourceMap": true, 20 | "resolveJsonModule": true 21 | }, 22 | "include": ["src", "bin"], 23 | "exclude": ["dist", "bundle", "node_modules"], 24 | "ts-node": { 25 | // these options are overrides used only by ts-node 26 | // same as the --compilerOptions flag and the TS_NODE_COMPILER_OPTIONS environment variable 27 | "compilerOptions": { 28 | "module": "commonjs" 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /apps/cli/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "tsup"; 2 | 3 | export default defineConfig({ 4 | entry: ["bin/run.ts"], 5 | splitting: false, 6 | sourcemap: false, 7 | clean: true, 8 | }); 9 | -------------------------------------------------------------------------------- /apps/cli/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | import { resolve } from "path"; 3 | 4 | export default defineConfig({ 5 | test: { 6 | globals: true, 7 | environment: "node", 8 | include: ["src/**/*.{test,spec}.{js,ts}"], 9 | exclude: ["node_modules", "dist", "bundle"], 10 | }, 11 | resolve: { 12 | alias: { 13 | "@": resolve(__dirname, "./src"), 14 | }, 15 | }, 16 | }); 17 | -------------------------------------------------------------------------------- /apps/docs/.github/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/docs/.github/screenshot.png -------------------------------------------------------------------------------- /apps/docs/.gitignore: -------------------------------------------------------------------------------- 1 | .next 2 | node_modules 3 | -------------------------------------------------------------------------------- /apps/docs/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Shu Ding 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /apps/docs/eslint.config.js: -------------------------------------------------------------------------------- 1 | import { nextJsConfig } from "@1chooo/eslint-config/next-js"; 2 | 3 | /** @type {import("eslint").Linter.Config} */ 4 | export default nextJsConfig; 5 | -------------------------------------------------------------------------------- /apps/docs/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | 5 | // NOTE: This file should not be edited 6 | // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. 7 | -------------------------------------------------------------------------------- /apps/docs/next.config.mjs: -------------------------------------------------------------------------------- 1 | import nextra from "nextra"; 2 | 3 | const withNextra = nextra({ 4 | search: true, 5 | defaultShowCopyCode: true, 6 | }); 7 | 8 | export default withNextra({ 9 | // ... Other Next.js config options 10 | // output: 'export' 11 | }); 12 | -------------------------------------------------------------------------------- /apps/docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "1chooo-com-docs", 3 | "version": "0.14.6", 4 | "private": true, 5 | "type": "module", 6 | "author": { 7 | "name": "Chun-Ho (Hugo) Lin", 8 | "email": "hugo@1chooo.com", 9 | "url": "https://1chooo.com" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/1chooo/portfolio" 14 | }, 15 | "description": "1chooo.com is a personal portfolio and blog website built with Next.js, React, and TypeScript. It features a modern design, supports Markdown content, and includes various interactive components.", 16 | "homepage": "https://1chooo.com", 17 | "scripts": { 18 | "dev": "next dev --port 3001", 19 | "build": "next build", 20 | "start": "next start", 21 | "lint": "next lint" 22 | }, 23 | "dependencies": { 24 | "lucide-react": "0.545.0", 25 | "next": "15.5.4", 26 | "nextra": "4.2.13", 27 | "nextra-theme-docs": "4.2.13", 28 | "react": "19.2.0", 29 | "react-dom": "19.2.0" 30 | }, 31 | "devDependencies": { 32 | "@1chooo/eslint-config": "workspace:*", 33 | "@1chooo/typescript-config": "workspace:*", 34 | "@types/node": "24.3.0", 35 | "@types/react": "19.2.2", 36 | "@types/react-dom": "19.2.2", 37 | "pagefind": "^1.3.0", 38 | "typescript": "^5.9.3" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /apps/docs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/docs/public/favicon.ico -------------------------------------------------------------------------------- /apps/docs/public/images/cover-transparent-with-1chooo-com.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/docs/public/images/cover-transparent-with-1chooo-com.png -------------------------------------------------------------------------------- /apps/docs/public/images/cover-transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/docs/public/images/cover-transparent.png -------------------------------------------------------------------------------- /apps/docs/public/images/cover-with-1chooo-com.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/docs/public/images/cover-with-1chooo-com.png -------------------------------------------------------------------------------- /apps/docs/public/images/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/docs/public/images/cover.png -------------------------------------------------------------------------------- /apps/docs/public/images/seo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/docs/public/images/seo.webp -------------------------------------------------------------------------------- /apps/docs/public/images/wiki/blog-before.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/docs/public/images/wiki/blog-before.png -------------------------------------------------------------------------------- /apps/docs/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/docs/public/logo192.png -------------------------------------------------------------------------------- /apps/docs/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/docs/public/logo512.png -------------------------------------------------------------------------------- /apps/docs/src/app/[[...mdxPath]]/page.tsx: -------------------------------------------------------------------------------- 1 | import { generateStaticParamsFor, importPage } from "nextra/pages"; 2 | import { useMDXComponents } from "../../mdx-components"; 3 | 4 | export const generateStaticParams = generateStaticParamsFor("mdxPath"); 5 | 6 | export async function generateMetadata(props) { 7 | const params = await props.params; 8 | const { metadata } = await importPage(params.mdxPath); 9 | return metadata; 10 | } 11 | 12 | const Wrapper = useMDXComponents().wrapper; 13 | 14 | export default async function Page(props) { 15 | const params = await props.params; 16 | const result = await importPage(params.mdxPath); 17 | const { default: MDXContent, toc, metadata } = result; 18 | return ( 19 | 20 | 21 | 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /apps/docs/src/content/_meta.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | index: "Welcome to 1chooo.com", 3 | "user-guide": "User Guide", 4 | stack: "Stack", 5 | "code-walkthrough": "Code Walkthrough", 6 | wiki: "Wiki", 7 | "change-log": "Change Log", 8 | acknowledgments: "Acknowledgments", 9 | contributing: "Contributing", 10 | demo: { 11 | type: "page", 12 | title: "Demo", 13 | href: "https://1chooo.com", 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /apps/docs/src/content/features.mdx: -------------------------------------------------------------------------------- 1 | # Features 2 | 3 | ## Tech Stack Highlights 4 | 5 | - Next.js 15 with App Router 6 | - TypeScript with strict configuration 7 | - Tailwind CSS for styling 8 | - Turborepo for monorepo management 9 | 10 | ## Blogging Essentials 11 | 12 | - Markdown support 13 | - Comment system 14 | - RSS feed 15 | - Sitemap generation 16 | - View counter 17 | - 🚧 Like button 18 | 19 | ## UI & UX Enhancements 20 | 21 | - Skeleton loading for better user experience 22 | - Responsive design for mobile and desktop 23 | - GitHub calendar heatmap to showcase contributions 24 | - Shiki for code syntax highlighting 25 | - Motion for animations 26 | 27 | ## Performance & SEO 28 | 29 | - Lighthouse score of nearly **100** 30 | - SEO optimized with meta tags and `JSON-LD` 31 | - Open graph images using `next/og` 32 | 33 |
34 | 1chooo.com Lighthouse Score 35 |
36 | 37 | ## Dev Experience 38 | 39 | - ESLint and Prettier for code quality 40 | - Conventional commit messages 41 | -------------------------------------------------------------------------------- /apps/docs/src/content/stack.mdx: -------------------------------------------------------------------------------- 1 | # Stack 2 | 3 | ## React 4 | 5 | ### Function Components 6 | 7 | We only use `FC` type when we need to pass and extract children from props [^1]. Otherwise, we use the function declaration. Refer [here](https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/function_components/) for a more extensive section explaining why `React.FC` should mostly be avoided. 8 | 9 | ```tsx {5} 10 | // Avoid 11 | interface Props { 12 | text?: string; 13 | } 14 | const Heading: React.FC = ({ text = 'Hello, world!' }) => { 15 | return

{text}

; 16 | }; 17 | ``` 18 | 19 | ```tsx {5} 20 | // Prefer 21 | interface Props { 22 | text?: string; 23 | } 24 | function Heading({text = 'Hello, world!'}: Props) { 25 | return

{text}

; 26 | } 27 | ``` 28 | 29 | 30 | ## Coding Patterns 31 | 32 | ### `let` vs `const` 33 | 34 | 35 | 36 | https://overreacted.io/on-let-vs-const/ 37 | 38 | Copy/paste is better than the wrong abstraction [^2]. 39 | 40 | ## UI/UX Design 41 | 42 | ### Hover Effects in Anchor Tags 43 | 44 | When designing hover effects for anchor tags, we use the following classes to style the anchor tags: 45 | 46 | ```tsx 47 | className="text-orange-yellow-crayola underline hover:text-opacity-70 hover:decoration-light-gray-70" 48 | ``` 49 | 50 | ## Footnotes 51 | 52 | [^1]: [Why "he" does not write React.FC on each function?](https://stackoverflow.com/questions/71189879/why-he-does-not-write-react-fc-on-each-function) 53 | [^2]: [Lee Robinson - Stack](https://leerob.com/n/stack) 54 | 55 | -------------------------------------------------------------------------------- /apps/docs/src/content/user-guide.mdx: -------------------------------------------------------------------------------- 1 | # User Guide 2 | 3 | [1chooo.com](https://1chooo.com) is a web application that allows users to showcase their projects and portfolios. This guide will help you get started with the website and customize it to your needs. 4 | 5 | -------------------------------------------------------------------------------- /apps/docs/src/mdx-components.ts: -------------------------------------------------------------------------------- 1 | import { useMDXComponents as getThemeComponents } from "nextra-theme-docs"; // nextra-theme-blog or your custom theme 2 | 3 | // Get the default MDX components 4 | const themeComponents = getThemeComponents(); 5 | 6 | // Merge components 7 | export const useMDXComponents: typeof getThemeComponents = (components) => { 8 | return { 9 | ...themeComponents, 10 | ...components, 11 | }; 12 | }; 13 | -------------------------------------------------------------------------------- /apps/docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@1chooo/typescript-config/react-library.json", 3 | "compilerOptions": { 4 | "target": "ES2017", 5 | "lib": ["dom", "dom.iterable", "esnext"], 6 | "allowJs": true, 7 | "skipLibCheck": true, 8 | "strict": false, 9 | "forceConsistentCasingInFileNames": true, 10 | "noEmit": true, 11 | "incremental": true, 12 | "esModuleInterop": true, 13 | "moduleResolution": "bundler", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "jsx": "preserve", 17 | "plugins": [ 18 | { 19 | "name": "next" 20 | } 21 | ], 22 | "module": "esnext", 23 | "baseUrl": ".", 24 | "paths": { 25 | "@/*": ["./src*"] 26 | } 27 | }, 28 | "include": ["next-env.d.ts", ".next/types/**/*.ts", "**/*.ts", "**/*.tsx"], 29 | "exclude": ["node_modules"] 30 | } 31 | -------------------------------------------------------------------------------- /apps/web/.env.example: -------------------------------------------------------------------------------- 1 | # Google Analytics and Google Tag Manager IDs 2 | NEXT_PUBLIC_GA_ID= 3 | NEXT_PUBLIC_GTM_ID= 4 | 5 | # Giscus Configuration 6 | NEXT_PUBLIC_GISCUS_CONFIG_REPO_ID= 7 | NEXT_PUBLIC_GISCUS_CONFIG_CATEGORY_ID= 8 | 9 | # Web3Forms Public Access Key 10 | NEXT_PUBLIC_WEB3FORMS_ACCESS_KEY= 11 | 12 | # Analytics with Umami 13 | # @see https://umami.is 14 | NEXT_PUBLIC_UMAMI_URL= 15 | NEXT_PUBLIC_UMAMI_WEBSITE_ID= 16 | -------------------------------------------------------------------------------- /apps/web/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | .swc 4 | 5 | 6 | .next 7 | 8 | # dependencies 9 | /node_modules 10 | /.pnp 11 | .pnp.js 12 | 13 | # testing 14 | /coverage 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | .env.local 22 | .env.development.local 23 | .env.test.local 24 | .env.production.local 25 | 26 | npm-debug.log* 27 | yarn-debug.log* 28 | yarn-error.log* 29 | -------------------------------------------------------------------------------- /apps/web/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "", 8 | "css": "../../packages/ui/src/styles/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true 11 | }, 12 | "iconLibrary": "lucide", 13 | "aliases": { 14 | "components": "@/components", 15 | "hooks": "@/hooks", 16 | "lib": "@/lib", 17 | "utils": "@1chooo/ui/lib/utils", 18 | "ui": "@1chooo/ui/components" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /apps/web/eslint.config.js: -------------------------------------------------------------------------------- 1 | import { nextJsConfig } from "@1chooo/eslint-config/next-js"; 2 | 3 | /** @type {import("eslint").Linter.Config} */ 4 | export default nextJsConfig; 5 | -------------------------------------------------------------------------------- /apps/web/mdx-components.tsx: -------------------------------------------------------------------------------- 1 | import type { MDXComponents } from "mdx/types"; 2 | 3 | export function useMDXComponents(components: MDXComponents): MDXComponents { 4 | return { 5 | ...components, 6 | h1: (props) =>

, 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | 5 | // NOTE: This file should not be edited 6 | // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. 7 | -------------------------------------------------------------------------------- /apps/web/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /apps/web/public/cv.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/cv.pdf -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/0001-two-sum.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/0001-two-sum.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/1052-grumpy-bookstore-owner.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/1052-grumpy-bookstore-owner.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/1382-balance-a-binary-search-tree.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/1382-balance-a-binary-search-tree.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/1480-running-sum-of-1d-array.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/1480-running-sum-of-1d-array.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/1550-three-consecutive-odds.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/1550-three-consecutive-odds.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/1791-find-center-of-star-graph.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/1791-find-center-of-star-graph.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/2181-merge-nodes-in-between-zeros.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/2181-merge-nodes-in-between-zeros.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/500-commits-milestone-in-1chooo-com.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/500-commits-milestone-in-1chooo-com.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/amazon-linux-2-install-docker.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/amazon-linux-2-install-docker.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/give-your-github-repos-a-makeover-with-vscodes-material-icons.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/give-your-github-repos-a-makeover-with-vscodes-material-icons.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/goodbye-react-create-app.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/goodbye-react-create-app.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/how-to-add-linear-gradient-effect-to-text.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/how-to-add-linear-gradient-effect-to-text.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/how-to-enable-word-wrap-mdx-files-in-vscode.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/how-to-enable-word-wrap-mdx-files-in-vscode.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/hugo-s-go-to-stack-for-building-maintainable-software.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/hugo-s-go-to-stack-for-building-maintainable-software.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/leetcode-november-2024-daily-challenge.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/leetcode-november-2024-daily-challenge.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/mac-install-nodejs-npm.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/mac-install-nodejs-npm.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/make-your-react-more-elegant-with-map.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/make-your-react-more-elegant-with-map.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/make-your-titles-more-readable-react-wrap-balancer.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/make-your-titles-more-readable-react-wrap-balancer.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/move-shared-components-to-global-layout.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/move-shared-components-to-global-layout.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/say-goodbye-to-git-graph-in-vscode.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/say-goodbye-to-git-graph-in-vscode.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/three-methods-to-access-environment-variable-values-in-python.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/three-methods-to-access-environment-variable-values-in-python.png -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/unknown-at-rule-tailwind-in-vscode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/unknown-at-rule-tailwind-in-vscode.png -------------------------------------------------------------------------------- /apps/web/public/images/banner/posts/who-is-chun-ho-hugo-lin.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/posts/who-is-chun-ho-hugo-lin.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/projects/1chooo-com.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/projects/1chooo-com.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/projects/anon-chat.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/projects/anon-chat.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/projects/aws-edu-101.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/projects/aws-edu-101.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/projects/evolving-beasts.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/projects/evolving-beasts.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/projects/game-scope.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/projects/game-scope.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/projects/gym-route.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/projects/gym-route.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/projects/hua-tank.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/projects/hua-tank.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/projects/ncufresh.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/projects/ncufresh.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/projects/refinaid.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/projects/refinaid.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/projects/thermal-calculator.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/projects/thermal-calculator.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/projects/todam-tw.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/projects/todam-tw.webp -------------------------------------------------------------------------------- /apps/web/public/images/banner/projects/uml-editor.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/banner/projects/uml-editor.webp -------------------------------------------------------------------------------- /apps/web/public/images/blog/chun-ho-hugo-lin/banner.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/blog/chun-ho-hugo-lin/banner.webp -------------------------------------------------------------------------------- /apps/web/public/images/blog/hugos-stack-standards/banner.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/blog/hugos-stack-standards/banner.webp -------------------------------------------------------------------------------- /apps/web/public/images/blog/placeholder.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/blog/placeholder.webp -------------------------------------------------------------------------------- /apps/web/public/images/blog/python-env/banner.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/blog/python-env/banner.webp -------------------------------------------------------------------------------- /apps/web/public/images/opengraph-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/opengraph-image.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/500-commit-achieving.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/500-commit-achieving.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/about.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/blog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/blog.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/contact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/contact.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/dependabot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/dependabot.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/ga.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/ga.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/milestone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/milestone.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/portfolio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/portfolio.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/readme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/readme.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/resume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/resume.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/tag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/tag.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/tests.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/tests.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/well-commits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/500-commits-milestone-in-1chooo-com/well-commits.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/cover.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/git-commit-message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/git-commit-message.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/git_tips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/git_tips.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/give-your-github-repos-a-makeover-with-vscodes-material-icons/add-to-your-chrmoe-based-browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/give-your-github-repos-a-makeover-with-vscodes-material-icons/add-to-your-chrmoe-based-browser.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/give-your-github-repos-a-makeover-with-vscodes-material-icons/before.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/give-your-github-repos-a-makeover-with-vscodes-material-icons/before.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/give-your-github-repos-a-makeover-with-vscodes-material-icons/final.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/give-your-github-repos-a-makeover-with-vscodes-material-icons/final.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/give-your-github-repos-a-makeover-with-vscodes-material-icons/my-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/give-your-github-repos-a-makeover-with-vscodes-material-icons/my-settings.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/give-your-github-repos-a-makeover-with-vscodes-material-icons/several-choices.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/give-your-github-repos-a-makeover-with-vscodes-material-icons/several-choices.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/goodbye-react-create-app/create-react-app-v-5-0-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/goodbye-react-create-app/create-react-app-v-5-0-1.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/goodbye-react-create-app/start-a-new-react-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/goodbye-react-create-app/start-a-new-react-project.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/how-to-add-linear-gradient-effect-to-text/after.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/how-to-add-linear-gradient-effect-to-text/after.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/how-to-add-linear-gradient-effect-to-text/before.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/how-to-add-linear-gradient-effect-to-text/before.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/how-to-add-linear-gradient-effect-to-text/final.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/how-to-add-linear-gradient-effect-to-text/final.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/how-to-add-linear-gradient-effect-to-text/linear-gradient-in-next-js-site.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/how-to-add-linear-gradient-effect-to-text/linear-gradient-in-next-js-site.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/how-to-add-linear-gradient-effect-to-text/selection-not-work.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/how-to-add-linear-gradient-effect-to-text/selection-not-work.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/how-to-enable-word-wrap-mdx-files-in-vscode/after.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/how-to-enable-word-wrap-mdx-files-in-vscode/after.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/how-to-enable-word-wrap-mdx-files-in-vscode/before.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/how-to-enable-word-wrap-mdx-files-in-vscode/before.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/how-to-enable-word-wrap-mdx-files-in-vscode/how-to-enable-word-wrap-mdx-files-in-vscode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/how-to-enable-word-wrap-mdx-files-in-vscode/how-to-enable-word-wrap-mdx-files-in-vscode.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/how-to-enable-word-wrap-mdx-files-in-vscode/toogle-word-wrap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/how-to-enable-word-wrap-mdx-files-in-vscode/toogle-word-wrap.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/make-your-titles-more-readable-react-wrap-balancer/demo-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/make-your-titles-more-readable-react-wrap-balancer/demo-01.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/make-your-titles-more-readable-react-wrap-balancer/demo-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/make-your-titles-more-readable-react-wrap-balancer/demo-02.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/no_ads.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/no_ads.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/nuphy_unboxing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/nuphy_unboxing.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/react_mapping_tips.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/react_mapping_tips.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/say-goodbye-to-git-graph-in-vscode/commit-details-in-git-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/say-goodbye-to-git-graph-in-vscode/commit-details-in-git-graph.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/say-goodbye-to-git-graph-in-vscode/git-graph-in-vscode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/say-goodbye-to-git-graph-in-vscode/git-graph-in-vscode.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/say-goodbye-to-git-graph-in-vscode/git-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/say-goodbye-to-git-graph-in-vscode/git-graph.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/say-goodbye-to-git-graph-in-vscode/say-goodbye-to-git-graph-in-vscode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/say-goodbye-to-git-graph-in-vscode/say-goodbye-to-git-graph-in-vscode.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/unknown-at-rule-tailwind-in-vscode/no-tailwind-alert-message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/unknown-at-rule-tailwind-in-vscode/no-tailwind-alert-message.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/unknown-at-rule-tailwind-in-vscode/search-postcss-language-support.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/unknown-at-rule-tailwind-in-vscode/search-postcss-language-support.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/unknown-at-rule-tailwind-in-vscode/unknown-tailwind-message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/unknown-at-rule-tailwind-in-vscode/unknown-tailwind-message.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/who-is-chun-ho-hugo-lin/postspark-1chooo-github-contributions-2024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/who-is-chun-ho-hugo-lin/postspark-1chooo-github-contributions-2024.png -------------------------------------------------------------------------------- /apps/web/public/images/posts/who-is-chun-ho-hugo-lin/postspark-1chooo-github-contributions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/posts/who-is-chun-ho-hugo-lin/postspark-1chooo-github-contributions.png -------------------------------------------------------------------------------- /apps/web/public/images/profile.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/profile.webp -------------------------------------------------------------------------------- /apps/web/public/images/project/1chooo-com/banner.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/project/1chooo-com/banner.webp -------------------------------------------------------------------------------- /apps/web/public/images/project/anon-chat/banner.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/project/anon-chat/banner.webp -------------------------------------------------------------------------------- /apps/web/public/images/project/jian-theme/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/project/jian-theme/banner.png -------------------------------------------------------------------------------- /apps/web/public/images/project/todam-tw/banner.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/project/todam-tw/banner.webp -------------------------------------------------------------------------------- /apps/web/public/images/project/tools/banner.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/project/tools/banner.webp -------------------------------------------------------------------------------- /apps/web/public/images/project/uml-editor/banner.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/public/images/project/uml-editor/banner.webp -------------------------------------------------------------------------------- /apps/web/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Chun-Ho (Hugo) Lin - 1chooo", 3 | "short_name": "1chooo.com", 4 | "categories": ["portfolio", "blog", "personal", "web development"], 5 | "description": "I'm Chun-Ho (Hugo) Lin, a graduate with a Bachelor's degree from National Central University (NCU) 🐿️, driven by a sincere passion for Software Engineering 💻.", 6 | "start_url": "/", 7 | "display": "standalone", 8 | "lang": "en-US", 9 | "background_color": "#fff", 10 | "theme_color": "#fff", 11 | "icons": [ 12 | { 13 | "src": "/favicon.ico", 14 | "sizes": "any", 15 | "type": "image/x-icon", 16 | "purpose": "any" 17 | }, 18 | { 19 | "src": "/favicon.ico", 20 | "sizes": "any", 21 | "type": "image/x-icon", 22 | "purpose": "maskable" 23 | }, 24 | { 25 | "src": "/favicon.ico", 26 | "sizes": "any", 27 | "type": "image/x-icon", 28 | "purpose": "monochrome" 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /apps/web/scripts/001-create-views-table.sql: -------------------------------------------------------------------------------- 1 | -- Create the page_views table 2 | CREATE TABLE IF NOT EXISTS page_views ( 3 | id SERIAL PRIMARY KEY, 4 | page VARCHAR(255) NOT NULL UNIQUE, 5 | views INTEGER NOT NULL DEFAULT 0, 6 | created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), 7 | updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() 8 | ); 9 | 10 | -- Insert initial record for profile page 11 | INSERT INTO page_views (page, views) 12 | VALUES ('/blog/test-post', 0) 13 | ON CONFLICT (page) DO NOTHING; 14 | 15 | -- Create an index on the page column for faster queries 16 | CREATE INDEX IF NOT EXISTS idx_page_views_page ON page_views(page); 17 | -------------------------------------------------------------------------------- /apps/web/src/app/(home)/(cookbook)/layout.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | function CookbookLayout({ children }: { readonly children: React.ReactNode }) { 4 | return
{children}
; 5 | } 6 | 7 | export default CookbookLayout; 8 | -------------------------------------------------------------------------------- /apps/web/src/app/(home)/(exp)/bookmarks/loading.tsx: -------------------------------------------------------------------------------- 1 | export default function Loading() { 2 | return null; 3 | } 4 | -------------------------------------------------------------------------------- /apps/web/src/app/(home)/(exp)/mdx/page.mdx: -------------------------------------------------------------------------------- 1 | import { ClickableTechBadges } from "@/lib/tech-badge/utils"; 2 | import PageTitle from "@/components/page-title"; 3 | import GitHubCalendar from "@1chooo/github-calendar"; 4 | import config from "@/config"; 5 | import AboutSection from "@/components/section/about"; 6 | 7 | export function Thing() { 8 | return <>World 9 | } 10 | 11 | export function GitHubMap() { 12 | const yellowTheme = { 13 | light: ["#EBEBEB", "#FFDA6B"], 14 | dark: ["#383838", "#FFDA6B"], 15 | }; 16 | 17 | return ( 18 | 19 |
20 | {config.about.githubUsername && ( 21 | 31 | )} 32 |
33 |
34 | ) 35 | } 36 | 37 | export const metadata = { 38 | title: 'MDX Demo', 39 | }; 40 | 41 |
42 | 43 | # Hello 44 | 45 | {ClickableTechBadges.typescript} 46 | 47 | 48 | 49 |
50 | -------------------------------------------------------------------------------- /apps/web/src/app/(home)/(exp)/og-image-generator/page.tsx: -------------------------------------------------------------------------------- 1 | import OGImageGenerator from "./og-image-generator"; 2 | import PageTitle from "@/components/page-title"; 3 | 4 | export const metadata = { 5 | title: "Chun-Ho (Hugo) Lin", 6 | description: 7 | "I am a first-year M.S. student in Computer Science at the [USC Viterbi School of Engineering](https://viterbischool.usc.edu/) ✌️. I graduated with a B.S. in Atmospheric Sciences from the [National Central University](https://www.ncu.edu.tw/) 🐿️.".slice( 8 | 0, 9 | 100, 10 | ) + "...", 11 | openGraph: { 12 | title: "Chun-Ho (Hugo) Lin", 13 | description: 14 | "I am a first-year M.S. student in Computer Science at the [USC Viterbi School of Engineering](https://viterbischool.usc.edu/) ✌️. I graduated with a B.S. in Atmospheric Sciences from the [National Central University](https://www.ncu.edu.tw/) 🐿️.".slice( 15 | 0, 16 | 100, 17 | ) + "...", 18 | url: "https://1chooo.com", 19 | siteName: "1chooo.com", 20 | images: [ 21 | { 22 | url: "/opengraph-image", 23 | width: 1200, 24 | height: 630, 25 | alt: "Chun-Ho (Hugo) Lin", 26 | }, 27 | ], 28 | locale: "en_US", 29 | type: "website", 30 | }, 31 | }; 32 | 33 | export default function Page() { 34 | return ( 35 |
36 | 37 | 38 |
39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /apps/web/src/app/(home)/(metadata)/llms-full.txt/route.ts: -------------------------------------------------------------------------------- 1 | export const dynamic = "force-static"; // or make it dynamic if you want 2 | 3 | import config from "@/config"; 4 | 5 | export function GET() { 6 | return new Response(config.llmsFullTxtContent); 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/src/app/(home)/(metadata)/llms.txt/route.ts: -------------------------------------------------------------------------------- 1 | export const dynamic = "force-static"; // or make it dynamic if you want 2 | 3 | import config from "@/config"; 4 | 5 | export function GET() { 6 | return new Response(config.llmsTxtContent); 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/src/app/(home)/(metadata)/rss.xml/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | import RSS from "rss"; 3 | import { getBlogPosts, getProjectPosts } from "@/lib/api/mdx"; 4 | import { BLOG_DIRECTORY, PROJECT_DIRECTORY } from "@/lib/constants"; 5 | import config from "@/config"; 6 | 7 | import type { ItemOptions } from "@/types/rss"; 8 | 9 | const { author, siteURL, rssOptions } = config; 10 | 11 | export async function GET() { 12 | const feed = new RSS(rssOptions); 13 | 14 | const posts = getBlogPosts(BLOG_DIRECTORY); 15 | 16 | for (const post of posts) { 17 | const { title, publishedAt, excerpt } = post; 18 | 19 | let itemOptions: ItemOptions; 20 | itemOptions = { 21 | title, 22 | url: `${siteURL}/blog/${post.slug}`, 23 | date: publishedAt, 24 | description: excerpt, 25 | author: author, 26 | }; 27 | 28 | feed.item(itemOptions); 29 | } 30 | 31 | const projects = getProjectPosts(PROJECT_DIRECTORY); 32 | 33 | for (const project of projects) { 34 | const { title, endDate, excerpt } = project; 35 | 36 | const projectDate = 37 | endDate && endDate.trim() !== "" ? endDate : new Date().toISOString(); 38 | 39 | let itemOptions: ItemOptions; 40 | itemOptions = { 41 | title, 42 | url: `${siteURL}/project/${project.slug}`, 43 | date: projectDate, 44 | description: excerpt, 45 | author: author, 46 | }; 47 | 48 | feed.item(itemOptions); 49 | } 50 | 51 | return new NextResponse(feed.xml({ indent: true }), { 52 | headers: { 53 | "Content-Type": "application/xml", 54 | }, 55 | }); 56 | } 57 | -------------------------------------------------------------------------------- /apps/web/src/app/(home)/[...rest]/page.tsx: -------------------------------------------------------------------------------- 1 | import { notFound } from "next/navigation"; 2 | 3 | export default function CatchAllPage() { 4 | notFound(); 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/(home)/code-of-conduct/page.tsx: -------------------------------------------------------------------------------- 1 | import PageTitle from "@/components/page-title"; 2 | import Mdx from "@/components/mdx"; 3 | import { FadeIn } from "@/components/animations/animations"; 4 | 5 | import { getCleanMdxContentFromPath } from "@/lib/api/mdx"; 6 | import { CODE_OF_CONDUCT_PATH } from "@/lib/constants"; 7 | 8 | export default async function CodeOfConduct() { 9 | return ( 10 |
11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 |
19 |
20 |
21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /apps/web/src/app/(home)/gallery/page.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import Link from "next/link"; 3 | import { BlurFadeDemo } from "@/components/magicui/blur-fade-demo"; 4 | import AnimatedGradientText from "@/components/magicui/animated-gradient-text"; 5 | import PageTitle from "@/components/page-title"; 6 | import config from "@/config"; 7 | import { ChevronRight } from "lucide-react"; 8 | import { cn } from "@1chooo/ui/lib/utils"; 9 | 10 | const { title } = config; 11 | 12 | export const metadata: Metadata = { 13 | title: `Gallery | ${title}`, 14 | }; 15 | 16 | function Gallery() { 17 | return ( 18 |
19 | 20 | 21 |
22 | 27 | 28 | 📑
{" "} 29 | 34 | Thanks for Magic UI! 35 | 36 | 37 |
38 | 39 |
40 |
41 | ); 42 | } 43 | 44 | export default Gallery; 45 | -------------------------------------------------------------------------------- /apps/web/src/app/(home)/page.tsx: -------------------------------------------------------------------------------- 1 | import dynamic from "next/dynamic"; 2 | 3 | import PageTitle from "@/components/page-title"; 4 | import { MyWritings } from "@/components/about/my-writings"; 5 | import { FadeLeft } from "@/components/animations/animations"; 6 | import { 7 | getBlogPosts, 8 | getCleanMdxContentFromPath, 9 | getProjectPosts, 10 | } from "@/lib/api/mdx"; 11 | import { ABOUT_PATH, BLOG_DIRECTORY, PROJECT_DIRECTORY } from "@/lib/constants"; 12 | 13 | const AboutSection = dynamic(() => import("@/components/section/about")); 14 | const Mdx = dynamic(() => import("@/components/mdx")); 15 | const SelectedProjects = dynamic( 16 | () => import("@/components/about/selected-projects"), 17 | ); 18 | 19 | function About() { 20 | const blogs = getBlogPosts(BLOG_DIRECTORY); 21 | const projects = getProjectPosts(PROJECT_DIRECTORY); 22 | 23 | return ( 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 42 | 43 |
44 | ); 45 | } 46 | 47 | export default About; 48 | -------------------------------------------------------------------------------- /apps/web/src/app/(home)/resume/page.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import type { Metadata } from "next"; 4 | 5 | import PageTitle from "@/components/page-title"; 6 | import ResumeTimeLine from "@/components/section/resume-timeline"; 7 | 8 | import type { ResumeTimeLineType } from "@/types/resume"; 9 | 10 | import config from "@/config"; 11 | 12 | const { title, resumes } = config; 13 | 14 | export const metadata: Metadata = { 15 | title: `Resume | ${title}`, 16 | }; 17 | 18 | export default function Resume() { 19 | return ( 20 |
21 | 22 | {(Object.entries(resumes) as [string, ResumeTimeLineType][]).map( 23 | ([key, resumeTimeLine]) => ( 24 | 30 | ), 31 | )} 32 |
33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /apps/web/src/app/(home)/terms/page.tsx: -------------------------------------------------------------------------------- 1 | import PageTitle from "@/components/page-title"; 2 | import Mdx from "@/components/mdx"; 3 | import { FadeIn } from "@/components/animations/animations"; 4 | 5 | import { getCleanMdxContentFromPath } from "@/lib/api/mdx"; 6 | import { TERMS_PATH } from "@/lib/constants"; 7 | 8 | async function Terms() { 9 | return ( 10 |
11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 |
19 |
20 |
21 | ); 22 | } 23 | 24 | export default Terms; 25 | -------------------------------------------------------------------------------- /apps/web/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1chooo/portfolio/1c9cffdae490858756adcc75b5afb90b877ec782/apps/web/src/app/favicon.ico -------------------------------------------------------------------------------- /apps/web/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | export default function RootLayout({ 2 | children, 3 | }: { 4 | readonly children: React.ReactNode; 5 | }) { 6 | return children; 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/src/app/opengraph-image.tsx: -------------------------------------------------------------------------------- 1 | import { ImageResponse } from "next/og"; 2 | import { join } from "node:path"; 3 | import { readFile } from "node:fs/promises"; 4 | 5 | export const alt = "Chun-Ho (Hugo) Lin - 1chooo"; 6 | export const size = { 7 | width: 1920, 8 | height: 1080, 9 | }; 10 | export const contentType = "image/png"; 11 | 12 | export default async function Image() { 13 | const logoData = await readFile( 14 | join(process.cwd(), "public", "images", "opengraph-image.png"), 15 | ); 16 | const imagePath = `data:image/png;base64,${logoData.toString("base64")}`; 17 | 18 | return new ImageResponse( 19 | ( 20 |
34 | ), 35 | { 36 | ...size, 37 | }, 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /apps/web/src/app/robots.ts: -------------------------------------------------------------------------------- 1 | import type { MetadataRoute } from "next"; 2 | import config from "@/config"; 3 | 4 | export default function robots(): MetadataRoute.Robots { 5 | return config.robots; 6 | } 7 | -------------------------------------------------------------------------------- /apps/web/src/app/sitemap.ts: -------------------------------------------------------------------------------- 1 | import type { MetadataRoute } from "next"; 2 | 3 | import { getProjectPosts, getBlogPosts } from "@/lib/api/mdx"; 4 | import { BLOG_DIRECTORY, PROJECT_DIRECTORY } from "@/lib/constants"; 5 | import config from "@/config"; 6 | 7 | const { siteURL } = config; 8 | 9 | function mapBlogPostsToSitemap( 10 | posts: { publishedAt: string; slug: string }[], 11 | prefix: string, 12 | ) { 13 | return posts.map((post) => ({ 14 | url: `${siteURL}/${prefix}/${post.slug}`, 15 | lastModified: post.publishedAt, 16 | })); 17 | } 18 | 19 | function mapProjectPostsToSitemap( 20 | projects: { endDate: string; slug: string }[], 21 | prefix: string, 22 | ) { 23 | return projects.map((project) => ({ 24 | url: `${siteURL}/${prefix}/${project.slug}`, 25 | lastModified: 26 | project.endDate && project.endDate.trim() !== "" 27 | ? project.endDate 28 | : new Date().toISOString(), 29 | })); 30 | } 31 | 32 | function sitemap(): MetadataRoute.Sitemap { 33 | const posts = getBlogPosts(BLOG_DIRECTORY); 34 | const postMaps = mapBlogPostsToSitemap(posts, "blog"); 35 | 36 | const projects = getProjectPosts(PROJECT_DIRECTORY); 37 | const projectMaps = mapProjectPostsToSitemap(projects, "project"); 38 | 39 | const routes = [ 40 | "", 41 | "/resume", 42 | "/project", 43 | "/blog", 44 | "/code-of-conduct", 45 | "/terms", 46 | "/cv", 47 | ].map((route) => ({ 48 | url: `${siteURL}${route}`, 49 | lastModified: new Date().toISOString().split("T")[0], 50 | })); 51 | 52 | return [...routes, ...postMaps, ...projectMaps]; 53 | } 54 | 55 | export default sitemap; 56 | -------------------------------------------------------------------------------- /apps/web/src/app/twitter-image.tsx: -------------------------------------------------------------------------------- 1 | import { ImageResponse } from "next/og"; 2 | import { join } from "node:path"; 3 | import { readFile } from "node:fs/promises"; 4 | 5 | export const alt = "Chun-Ho (Hugo) Lin - 1chooo"; 6 | export const size = { 7 | width: 1920, 8 | height: 1080, 9 | }; 10 | export const contentType = "image/png"; 11 | 12 | export default async function Image() { 13 | const logoData = await readFile( 14 | join(process.cwd(), "public", "images", "opengraph-image.png"), 15 | ); 16 | const imagePath = `data:image/png;base64,${logoData.toString("base64")}`; 17 | 18 | return new ImageResponse( 19 | ( 20 |
34 | ), 35 | { 36 | ...size, 37 | }, 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /apps/web/src/components/about/life-styles.tsx: -------------------------------------------------------------------------------- 1 | import GradientCard from "@/components/gradient-card"; 2 | import { BlurFade } from "@/components/magicui/blur-fade"; 3 | import { getIcon } from "@/components/icons"; 4 | 5 | import type { LifeStyle } from "@/types/about"; 6 | 7 | interface LifeStylesProps { 8 | lifestyles: LifeStyle[]; 9 | } 10 | 11 | function LifeStyles({ lifestyles }: LifeStylesProps) { 12 | return ( 13 | 14 |
15 | {lifestyles.map((lifestyle: LifeStyle, index) => { 16 | const Icon = getIcon(lifestyle.icon); 17 | 18 | return ( 19 | 23 |
24 | 25 |
26 | 27 |
28 |

29 | {lifestyle.title} 30 |

31 |

32 | {lifestyle.text} 33 |

34 |
35 |
36 | ); 37 | })} 38 |
39 |
40 | ); 41 | } 42 | 43 | export { LifeStyles }; 44 | export default LifeStyles; 45 | -------------------------------------------------------------------------------- /apps/web/src/components/about/see-more-button.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { sendGTMEvent } from "@next/third-parties/google"; 3 | import { ViewTransitionsProgressBarLink } from "@/components/progress-bar"; 4 | 5 | import type { VCardIconType } from "@/types/config"; 6 | 7 | interface SeeMoreButtonProps { 8 | badge: string; 9 | path: string; 10 | icon: VCardIconType; 11 | } 12 | 13 | // TODO: customize button onclick effect https://articles.readytowork.jp/google-analytics-in-next-js-a26cc2b28db5 14 | function SeeMoreButton({ badge, path, icon: Icon }: SeeMoreButtonProps) { 15 | return ( 16 |
17 | 18 | 30 | 31 |
32 | ); 33 | } 34 | 35 | export { SeeMoreButton }; 36 | export default SeeMoreButton; 37 | -------------------------------------------------------------------------------- /apps/web/src/components/analytics/google.tsx: -------------------------------------------------------------------------------- 1 | import { GoogleAnalytics, GoogleTagManager } from "@next/third-parties/google"; 2 | 3 | interface GoogleAnalyticProps { 4 | googleAnalyticId: string; 5 | googleTagManagerId: string; 6 | } 7 | 8 | function GoogleAnalytic({ 9 | googleAnalyticId, 10 | googleTagManagerId, 11 | }: GoogleAnalyticProps) { 12 | return ( 13 | <> 14 | 15 | 16 | 17 | ); 18 | } 19 | 20 | export default GoogleAnalytic; 21 | export { GoogleAnalytic }; 22 | -------------------------------------------------------------------------------- /apps/web/src/components/analytics/index.tsx: -------------------------------------------------------------------------------- 1 | import { GoogleAnalytic } from "@/components/analytics/google"; 2 | import { UmamiAnalytic } from "@/components/analytics/umami"; 3 | import { VercelAnalytic } from "@/components/analytics/vercel"; 4 | 5 | export { GoogleAnalytic, UmamiAnalytic, VercelAnalytic }; 6 | -------------------------------------------------------------------------------- /apps/web/src/components/analytics/umami.tsx: -------------------------------------------------------------------------------- 1 | import Script from "next/script"; 2 | 3 | interface UmamiAnalyticProps { 4 | umamiWebsiteId: string; 5 | umamiUrl: string; 6 | } 7 | 8 | function UmamiAnalytic({ umamiWebsiteId, umamiUrl }: UmamiAnalyticProps) { 9 | return ( 10 |