Skip to content

Commit

Permalink
Merge pull request #16 from route06inc/i18n-directory
Browse files Browse the repository at this point in the history
feat: Restructure 'contents' directory and update routing
  • Loading branch information
junkisai authored Oct 7, 2024
2 parents af4bb99 + b18a23f commit 675c0b4
Show file tree
Hide file tree
Showing 36 changed files with 334 additions and 28 deletions.
14 changes: 11 additions & 3 deletions frontend/apps/service-site/contentlayer.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { defineDocumentType, makeSource } from 'contentlayer/source-files'

export const Post = defineDocumentType(() => ({
name: 'Post',
filePathPattern: 'posts/*.md',
filePathPattern: 'posts/*/*.md',
fields: {
title: { type: 'string', required: true },
date: { type: 'date', required: true },
Expand All @@ -25,12 +25,20 @@ export const Post = defineDocumentType(() => ({
introduction: { type: 'string', required: true },
},
computedFields: {
href: { type: 'string', resolve: (post) => `/${post._raw.flattenedPath}` },
lang: {
type: 'string',
resolve: (post) => {
// ex. segments = [ 'posts', '1', 'en' ]
const segments = post._raw.flattenedPath.split('/')
return segments[2]
},
},
slug: {
type: 'string',
resolve: (post) => {
// ex. segments = [ 'posts', '1', 'en' ]
const segments = post._raw.flattenedPath.split('/')
return segments[segments.length - 1]
return segments[1]
},
},
},
Expand Down
34 changes: 34 additions & 0 deletions frontend/apps/service-site/contents/posts/1/ja.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: 'ノーコード革命:プログラマーでなくてもアプリを作れる新時代'
date: 2024-09-27
tags:
- Democratization
- Empowerment
- Innovation
- Agility
- Disruption
categories:
- Technology
- App Development
image: /images/posts/1/image.png
writer: Aiden Sparks
introduction: "テクノロジーが急速に進化する世界で、ソフトウェアアプリケーションの需要がかつてないほど高まっています。しかし、深いコーディング知識を必要とする従来のアプリ開発アプローチは、多くの個人や企業にとってしばしば障壁となってきました。そこで登場したのが、アプリ開発プロセスを民主化する画期的な動きであるノーコード革命です。もはや、強力で機能的なアプリを作成するために熟練したプログラマーである必要はありません。今日では、創造的なアイデアと基本的なコンピュータースキルを持つ誰もが、ノーコードプラットフォームを使用して自分のビジョンを実現できるのです。"
---

ノーコードアプリケーションプラットフォームの台頭は、ソフトウェア開発の景観を変えつつあります。これらのプラットフォームにより、コーディングの知識がほとんどないユーザーでも完全に機能するアプリケーションを作成できるようになり、イノベーションへの参入障壁が低くなっています。ノーコードツールが提供する利便性、柔軟性、スピードは、あらゆる規模の企業が前例のないペースでイノベーションを起こすのに役立っています。

## ノーコードプラットフォームとは?

ノーコードプラットフォームは、開発者や非開発者でも、ドラッグアンドドロップ機能や事前に構築されたコンポーネントを通じてアプリケーションを構築できるユーザーフレンドリーなインターフェースを提供します。これらのプラットフォームは従来のコーディングの複雑さを抽象化し、ビジョンを持つ誰もがアイデアを実現できるようにします。

## ノーコードプラットフォームの利点

1. **スピードと俊敏性**: ノーコードプラットフォームは、迅速なプロトタイピングと開発を可能にし、製品を市場に投入するまでの時間を短縮します。
2. **コスト効率**: 専任の開発チームが不要になるため、企業は大幅にコストを削減できます。
3. **エンパワーメント**: ビジネスユーザーが自らアプリケーションを作成できるようになり、IT部門への依存度が低下します。

## ノーコードの未来

ノーコードプラットフォームの機能が拡大し続けるにつれ、1行のコードも書くことなく、より複雑なアプリケーションを構築できるようになります。AI統合と自動化は、ノーコード開発の次のフロンティアであり、さらなるイノベーションの機会を提供します。

ノーコード運動は、アプリ開発プロセスを民主化し、より多くの人々がソフトウェアの未来を創造することに参加できるようにしています。これらのプラットフォームが進化するにつれ、開発者と非開発者の境界線がさらに曖昧になり、アプリ開発が誰にでもアクセス可能になるでしょう。
34 changes: 34 additions & 0 deletions frontend/apps/service-site/contents/posts/2/ja.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: 'ノーコードアプリ開発を成功させるための5つのベストプラクティス'
date: 2024-09-26
tags:
- Vision
- Scalability
- User-Centric
- Automation
- Iteration
categories:
- Technology
- App Development
image: /images/posts/2/image.png
writer: Nico Blaze
introduction: "ノーコードプラットフォームの台頭により、アプリ開発へのアプローチが変革されました。従来のコーディングスキルを持たない個人でも完全に機能するアプリケーションを構築できるようになり、ノーコードツールは企業、起業家、クリエイターに無限の可能性をもたらしました。しかし、ノーコードの力を最大限に活用するには、プロジェクトの成功とスケーラビリティを確保するベストプラクティスに従うことが不可欠です。ここでは、ノーコードアプリ開発の旅を最大限に活用するための5つのベストプラクティスを紹介します。"
---

ノーコードアプリケーションプラットフォームの台頭は、ソフトウェア開発の景観を変えつつあります。これらのプラットフォームにより、コーディングの知識がほとんどないユーザーでも完全に機能するアプリケーションを作成できるようになり、イノベーションへの参入障壁が低くなっています。ノーコードツールが提供する利便性、柔軟性、スピードは、あらゆる規模の企業が前例のないペースでイノベーションを起こすのに役立っています。

## ノーコードプラットフォームとは?

ノーコードプラットフォームは、開発者や非開発者でも、ドラッグアンドドロップ機能や事前に構築されたコンポーネントを通じてアプリケーションを構築できるユーザーフレンドリーなインターフェースを提供します。これらのプラットフォームは従来のコーディングの複雑さを抽象化し、ビジョンを持つ誰もがアイデアを実現できるようにします。

## ノーコードプラットフォームの利点

1. **スピードと俊敏性**: ノーコードプラットフォームは、迅速なプロトタイピングと開発を可能にし、製品を市場に投入するまでの時間を短縮します。
2. **コスト効率**: 専任の開発チームが不要になるため、企業は大幅にコストを削減できます。
3. **エンパワーメント**: ビジネスユーザーが自らアプリケーションを作成できるようになり、IT部門への依存度が低下します。

## ノーコードの未来

ノーコードプラットフォームの機能が拡大し続けるにつれ、1行のコードも書くことなく、より複雑なアプリケーションを構築できるようになります。AI統合と自動化は、ノーコード開発の次のフロンティアであり、さらなるイノベーションの機会を提供します。

ノーコード運動は、アプリ開発プロセスを民主化し、より多くの人々がソフトウェアの未来を創造することに参加できるようにしています。これらのプラットフォームが進化するにつれ、開発者と非開発者の境界線がさらに曖昧になり、アプリ開発が誰にでもアクセス可能になるでしょう。
32 changes: 32 additions & 0 deletions frontend/apps/service-site/contents/posts/3/ja.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
title: '2024年のノーコードトレンド:注目の新機能とプラットフォーム'
date: 2024-09-25
tags:
- No-code
- App Development
- Tech Trends
categories:
- Technology
- App Development
image: /images/posts/3/image.png
writer: Dexter Quinn
introduction: "ノーコードプラットフォームは、従来のコーディングスキルなしでソフトウェアを作成できるようにすることで、企業のアプリケーション開発へのアプローチを革新しています。この記事では、ノーコードプラットフォームのテクノロジー業界への深い影響と、将来の展望について探ります。まず、ノーコードプラットフォームの出現により、ソフトウェア開発が民主化され、専門的なプログラミング知識を持つ人々を超えて、はるかに幅広い層にアクセス可能になりました。この変化により、イノベーションへの障壁が大幅に低下し、多様なアイデアが実現可能になりました。直感的なビジュアルインターフェースと事前構築されたコンポーネントを提供することで、これらのプラットフォームは様々な背景を持つ個人がコンセプトを機能的なアプリケーションに変換することを可能にしています。"
---

ノーコードアプリケーションプラットフォームの台頭は、ソフトウェア開発の景観を変えつつあります。これらのプラットフォームにより、コーディングの知識がほとんどないユーザーでも完全に機能するアプリケーションを作成できるようになり、イノベーションへの参入障壁が低くなっています。ノーコードツールが提供する利便性、柔軟性、スピードは、あらゆる規模の企業が前例のないペースでイノベーションを起こすのに役立っています。

## ノーコードプラットフォームとは?

ノーコードプラットフォームは、開発者や非開発者でも、ドラッグアンドドロップ機能や事前に構築されたコンポーネントを通じてアプリケーションを構築できるユーザーフレンドリーなインターフェースを提供します。これらのプラットフォームは従来のコーディングの複雑さを抽象化し、ビジョンを持つ誰もがアイデアを実現できるようにします。

## ノーコードプラットフォームの利点

1. **スピードと俊敏性**: ノーコードプラットフォームは、迅速なプロトタイピングと開発を可能にし、製品を市場に投入するまでの時間を短縮します。
2. **コスト効率**: 専任の開発チームが不要になるため、企業は大幅にコストを削減できます。
3. **エンパワーメント**: ビジネスユーザーが自らアプリケーションを作成できるようになり、IT部門への依存度が低下します。

## ノーコードの未来

ノーコードプラットフォームの機能が拡大し続けるにつれ、1行のコードも書くことなく、より複雑なアプリケーションを構築できるようになります。AI統合と自動化は、ノーコード開発の次のフロンティアであり、さらなるイノベーションの機会を提供します。

ノーコード運動は、アプリ開発プロセスを民主化し、より多くの人々がソフトウェアの未来を創造することに参加できるようにしています。これらのプラットフォームが進化するにつれ、開発者と非開発者の境界線がさらに曖昧になり、アプリ開発が誰にでもアクセス可能になるでしょう。
4 changes: 3 additions & 1 deletion frontend/apps/service-site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"lint": "conc -c auto pnpm:lint:*",
"lint:biome": "biome check .",
"lint:next": "next lint",
"lint:tsc": "tsc --noEmit",
"fmt": "conc -c auto pnpm:fmt:*",
"fmt:biome": "biome check --write --unsafe ."
},
Expand All @@ -26,7 +27,8 @@
"remark-gfm": "^4.0.0",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.1",
"unified": "^11.0.5"
"unified": "^11.0.5",
"valibot": "1.0.0-beta.0"
},
"devDependencies": {
"@biomejs/biome": "1.9.3",
Expand Down
25 changes: 25 additions & 0 deletions frontend/apps/service-site/src/app/[lang]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { TopCards } from '@/components'
import { langSchema, langs } from '@/i18n'
import { filterPostsByLang } from '@/utils/posts'
import { compareDesc } from 'date-fns'
import { object, parse } from 'valibot'
import type { PageProps } from '../types'

export const generateStaticParams = async () => {
return langs.map((lang) => ({ lang }))
}

const paramsSchema = object({
lang: langSchema,
})

export default function Page({ params }: PageProps) {
const { lang } = parse(paramsSchema, params)

const posts = filterPostsByLang(lang)
const sortedPosts = posts.sort((a, b) =>
compareDesc(new Date(a.date), new Date(b.date)),
)

return <TopCards posts={sortedPosts.slice(0, 14)} lang={lang} />
}
47 changes: 47 additions & 0 deletions frontend/apps/service-site/src/app/[lang]/posts/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { PageProps } from '@/app/types'
import { langSchema, langs } from '@/i18n'
import { findPostByLangAndSlug } from '@/utils/posts'
import { allPosts } from 'contentlayer/generated'
import { format, parseISO } from 'date-fns'
import { notFound } from 'next/navigation'
import { object, parse, string } from 'valibot'

export const generateStaticParams = async () => {
return langs.map((lang) => {
return allPosts.map((post) => ({ slug: post.slug, lang }))
})
}

export const generateMetadata = ({ params }: PageProps) => {
const { lang, slug } = parse(paramsSchema, params)
const post = findPostByLangAndSlug({ lang, slug })

if (!post) notFound()

return { title: post.title }
}

const paramsSchema = object({
lang: langSchema,
slug: string(),
})

export default function Page({ params }: PageProps) {
const { lang, slug } = parse(paramsSchema, params)

const post = findPostByLangAndSlug({ lang, slug })
if (!post) notFound()

return (
<article>
<div>
<time dateTime={post.date}>
{format(parseISO(post.date), 'LLLL d, yyyy')}
</time>
<h1>{post.title}</h1>
</div>
{/* biome-ignore lint/security/noDangerouslySetInnerHtml: <explanation> */}
<div dangerouslySetInnerHTML={{ __html: post.body.html }} />
</article>
)
}
48 changes: 48 additions & 0 deletions frontend/apps/service-site/src/app/[lang]/posts/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { PageProps } from '@/app/types'
import { langSchema, langs } from '@/i18n'
import { filterPostsByLang } from '@/utils/posts'
import type { Post } from 'contentlayer/generated'
import { compareDesc, format, parseISO } from 'date-fns'
import Link from 'next/link'
import { object, parse } from 'valibot'

function PostCard(post: Post) {
return (
<div>
<h2>
<Link href={`/${post.lang}/posts/${post.slug}`}>{post.title}</Link>
</h2>
<time dateTime={post.date}>
{format(parseISO(post.date), 'LLLL d, yyyy')}
</time>
{/* biome-ignore lint/security/noDangerouslySetInnerHtml: No problem, as it is only via Markdown written by in-house members. */}
<div dangerouslySetInnerHTML={{ __html: post.body.html }} />
</div>
)
}

export const generateStaticParams = async () => {
return langs.map((lang) => ({ lang }))
}

const paramsSchema = object({
lang: langSchema,
})

export default function Page({ params }: PageProps) {
const { lang } = parse(paramsSchema, params)

const posts = filterPostsByLang(lang)
const sortedPosts = posts.sort((a, b) =>
compareDesc(new Date(a.date), new Date(b.date)),
)

return (
<div>
<h1>Posts</h1>
{sortedPosts.map((post) => (
<PostCard key={post.slug} {...post} />
))}
</div>
)
}
7 changes: 6 additions & 1 deletion frontend/apps/service-site/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Metadata } from 'next'
import '@/styles/globals.css'
import { Footer, Header } from '@/components'
import type { Lang } from '@/i18n'
import type { ReactNode } from 'react'

export const metadata: Metadata = {
Expand All @@ -10,11 +11,15 @@ export const metadata: Metadata = {

export default function RootLayout({
children,
params: { lang },
}: Readonly<{
children: ReactNode
params: {
lang: Lang
}
}>) {
return (
<html lang="en">
<html lang={lang}>
<body>
<Header />
<main>{children}</main>
Expand Down
12 changes: 7 additions & 5 deletions frontend/apps/service-site/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { allPosts } from 'contentlayer/generated'
import { TopCards } from '@/components'
import { fallbackLang } from '@/i18n'
import { filterPostsByLang } from '@/utils/posts'
import { compareDesc } from 'date-fns'
import { TopCards } from '../components'

export default function Home() {
const posts = allPosts.sort((a, b) =>
export default function Page() {
const posts = filterPostsByLang(fallbackLang)
const sortedPosts = posts.sort((a, b) =>
compareDesc(new Date(a.date), new Date(b.date)),
)

return <TopCards posts={posts.slice(0, 14)} />
return <TopCards posts={sortedPosts.slice(0, 14)} />
}
31 changes: 19 additions & 12 deletions frontend/apps/service-site/src/app/posts/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
import type { PageProps } from '@/app/types'
import { fallbackLang } from '@/i18n'
import { findPostByLangAndSlug } from '@/utils/posts'
import { allPosts } from 'contentlayer/generated'
import { format, parseISO } from 'date-fns'

const getPost = (slug: string) => {
return allPosts.find((post) => post.slug === slug)
}
import { notFound } from 'next/navigation'
import { object, parse, string } from 'valibot'

export const generateStaticParams = async () =>
allPosts.map((post) => ({ slug: post.slug }))

export const generateMetadata = ({ params }: { params: { slug: string } }) => {
const post = getPost(params.slug)
export const generateMetadata = ({ params }: PageProps) => {
const { slug } = parse(paramsSchema, params)
const post = findPostByLangAndSlug({ lang: fallbackLang, slug })

if (!post) notFound()

if (!post) throw new Error(`Post not found for slug: ${params.slug}`)
return { title: post.title }
}

const PostLayout = ({ params }: { params: { slug: string } }) => {
const post = getPost(params.slug)
if (!post) throw new Error(`Post not found for slug: ${params.slug}`)
const paramsSchema = object({
slug: string(),
})

export default function Page({ params }: PageProps) {
const { slug } = parse(paramsSchema, params)

const post = findPostByLangAndSlug({ lang: fallbackLang, slug })
if (!post) notFound()

return (
<article>
Expand All @@ -32,5 +41,3 @@ const PostLayout = ({ params }: { params: { slug: string } }) => {
</article>
)
}

export default PostLayout
Loading

0 comments on commit 675c0b4

Please sign in to comment.