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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,7 @@ export interface ITutorial {
published?: string | null
lang: string
isExternal: boolean
isTranslated?: boolean
}

export enum AppCategoryEnum {
Expand Down
64 changes: 34 additions & 30 deletions src/lib/utils/md.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { dateToString } from "@/lib/utils/date"

import internalTutorialSlugs from "@/data/internalTutorials.json"

import { CONTENT_DIR, SITE_URL } from "@/lib/constants"
import { CONTENT_DIR, DEFAULT_LOCALE } from "@/lib/constants"

import { toPosixPath } from "./relativePath"

Expand Down Expand Up @@ -75,28 +75,39 @@ export const getPostSlugs = async (dir: string, filterRegex?: RegExp) => {
export const getTutorialsData = async (
locale: string
): Promise<ITutorial[]> => {
const tutorialData: ITutorial[] = []

// Fetch tutorials from public URLs in parallel
// Read tutorials from filesystem in parallel using dynamic imports
const tutorialPromises = (internalTutorialSlugs as string[]).map(
async (slug) => {
try {
const path =
locale !== "en"
? `/content/translations/${locale}/developers/tutorials/${slug}/index.md`
: `/content/developers/tutorials/${slug}/index.md`

const url = new URL(path, SITE_URL).toString()

const response = await fetch(url)
if (!response.ok) {
console.warn(
`Failed to fetch tutorial ${slug} for locale ${locale}: ${response.status}`
)
return null
let fileContents: string
let isTranslated = true

if (locale === DEFAULT_LOCALE) {
// English: read directly from content directory
fileContents = (
await import(
`../../../public/content/developers/tutorials/${slug}/index.md`
)
).default
} else {
// Non-English: try translation first, fallback to English
try {
fileContents = (
await import(
`../../../public/content/translations/${locale}/developers/tutorials/${slug}/index.md`
)
).default
} catch {
// Fallback to English content
fileContents = (
await import(
`../../../public/content/developers/tutorials/${slug}/index.md`
)
).default
isTranslated = false
}
}

const fileContents = await response.text()
const { data, content } = matter(fileContents)
const frontmatter = data as Frontmatter

Expand All @@ -111,27 +122,20 @@ export const getTutorialsData = async (
published: dateToString(frontmatter.published),
lang: frontmatter.lang,
isExternal: false,
isTranslated,
}
} catch (error) {
console.warn(
`Error fetching tutorial ${slug} for locale ${locale}:`,
error
)
// Only warn if English content is missing (actual error)
console.warn(`Error reading tutorial ${slug}:`, error)
return null
}
}
)

const results = await Promise.all(tutorialPromises)

// Filter out null results (failed fetches)
results.forEach((tutorial) => {
if (tutorial) {
tutorialData.push(tutorial)
}
})

return tutorialData
// Filter out null results (missing tutorials)
return results.filter((tutorial) => tutorial !== null) as ITutorial[]
}

export const checkPathValidity = (
Expand Down