diff --git a/docs/design.md b/docs/design.md
index 7be30d95a..5b35b6476 100644
--- a/docs/design.md
+++ b/docs/design.md
@@ -83,6 +83,29 @@ Behance 用户主页 URL 获取用户名,如
+## Notefolio
+
+### Works
+
+
+
+| 分类 | 韩文分类名 | 中文分类名 |
+| ---- | --------------- | --------------- |
+| all | 전체 | 全部 |
+| A7 | 공예 | 工艺品 |
+| J7 | 그래픽 디자인 | 平面设计 |
+| B7 | 디지털 아트 | 数字艺术 |
+| C7 | 영상/모션그래픽 | 视频 / 图形动画 |
+| D7 | 브랜딩/편집 | 品牌创建 / 编辑 |
+| E7 | 산업 디자인 | 工业设计 |
+| F7 | UI/UX | UI/UX |
+| G7 | 일러스트레이션 | 插画 |
+| K7 | 타이포그래피 | 字体 |
+| H7 | 파인아트 | 纯艺术 |
+| I7 | 포토그래피 | 摄影 |
+
+
+
## UI 中国
### 推荐文章
diff --git a/docs/en/design.md b/docs/en/design.md
index e945105cb..7f9689856 100644
--- a/docs/en/design.md
+++ b/docs/en/design.md
@@ -77,6 +77,29 @@ Default is under 'https://www.methodstudios.com/en/features'.
+## Notefolio
+
+### Works
+
+
+
+| Category | Name in Korean | Name in English |
+| -------- | -------------- | --------------- |
+| all | 전체 | All |
+| A7 | 공예 | Crafts |
+| J7 | 그래픽 디자인 | Graphic Design |
+| B7 | 디지털 아트 | Digital Art |
+| C7 | 영상/모션그래픽 | Video / Motion Graphics |
+| D7 | 브랜딩/편집 | Branding / Editing |
+| E7 | 산업 디자인 | Industrial Design |
+| F7 | UI/UX | UI/UX |
+| G7 | 일러스트레이션 | Illustration |
+| K7 | 타이포그래피 | Typography |
+| H7 | 파인아트 | Fine Art |
+| I7 | 포토그래피 | Photography |
+
+
+
## Unit Image
### Films
diff --git a/lib/router.js b/lib/router.js
index 25c0cee9c..bd3280552 100644
--- a/lib/router.js
+++ b/lib/router.js
@@ -3241,6 +3241,9 @@ router.get('/appsales/:caty?/:time?', require('./routes/appsales/index'));
// CGTN
router.get('/cgtn/top', require('./routes/cgtn/top'));
+// notefolio
+router.get('/notefolio/:caty?/:order?/:time?/:query?', require('./routes/notefolio/index'));
+
// JavDB
router.get('/javdb/home/:caty?/:sort?/:filter?', require('./routes/javdb/home'));
router.get('/javdb/search/:keyword?/:filter?', require('./routes/javdb/search'));
diff --git a/lib/routes/notefolio/index.js b/lib/routes/notefolio/index.js
new file mode 100644
index 000000000..c92317858
--- /dev/null
+++ b/lib/routes/notefolio/index.js
@@ -0,0 +1,68 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+
+module.exports = async (ctx) => {
+ const caty = ctx.params.caty || 'all';
+ const order = ctx.params.order || 'pick';
+ const time = ctx.params.time || 'all';
+ const query = ctx.params.query || '';
+
+ const rootUrl = `https://notefolio.net/?work_categories=${caty === 'all' ? '' : caty}&order=${order}&from=${time}&q=${query}`;
+ const response = await got({
+ method: 'get',
+ url: rootUrl,
+ });
+
+ const $ = cheerio.load(response.data);
+
+ $('div.mobile-category-order').remove();
+
+ const list = $('div.work-list div.work-list-item')
+ .slice(0, 5)
+ .map((_, item) => {
+ item = $(item);
+ const a = item.find('a.go-to-work-info').eq(0);
+ return {
+ title: item.find('div.title').text(),
+ link: `https://notefolio.net${a.attr('href')}`,
+ author: item.find('span.go-profile-area').text(),
+ };
+ })
+ .get();
+
+ const items = await Promise.all(
+ list.map(
+ async (item) =>
+ await ctx.cache.tryGet(item.link, async () => {
+ const detailResponse = await got({
+ method: 'get',
+ url: item.link,
+ });
+
+ const content = cheerio.load(detailResponse.data);
+
+ item.description = '
';
+
+ content('li.block-image a img').each((_, i) => {
+ i = content(i);
+ item.description += `})
`;
+ });
+
+ content('li.block-video iframe').each((_, i) => {
+ i = content(i);
+ item.description += ``;
+ });
+
+ item.description += `- ${content('li.block-text').html()}
`;
+
+ return item;
+ })
+ )
+ );
+
+ ctx.state.data = {
+ title: `${$('title').text()}`,
+ link: rootUrl,
+ item: items,
+ };
+};