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
28 changes: 28 additions & 0 deletions content/classes/sample-python-fundamentals.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
title: Myanmar Python Fundamentals (Sample)
description: >-
An introductory class covering Python syntax, problem-solving basics,
data structures, and scripting practice for students transitioning into
software development.
instructorName: Community Python Mentor Group
classLink: https://example.com/classes/python-fundamentals
tags:
- Python
- Programming Basics
- Backend
classType: In-Person
status: incoming
proofOfAssociation: >-
Submitter is a currently enrolled student and shared enrollment confirmation
plus class orientation details in the pull request for manual verification.
---

### Trust Context

- Submitter role: Attending student (learning side).
- Class legitimacy: This entry demonstrates the required credibility narrative for a moderated listing.

### Notes

- Schedule and venue details are managed through the official class link.
- Listing appears only after maintainer approval.
29 changes: 29 additions & 0 deletions content/classes/sample-react-bootcamp.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
title: MMSWE React Bootcamp (Sample)
description: >-
A structured React bootcamp focused on modern frontend fundamentals:
component architecture, state management, routing, API integration, and
deployment workflow for beginner-to-intermediate learners.
instructorName: MMSWE Education Team
classLink: https://example.com/classes/react-bootcamp
tags:
- React
- TypeScript
- Frontend
classType: online
status: active
proofOfAssociation: >-
Submitter is a teaching assistant in the class and provided internal schedule
screenshots plus mentor confirmation to maintainers during PR review.
---

### Trust Context

- Submitter role: Teaching assistant (teaching side).
- Class legitimacy: This entry represents a sample verified listing format for the curated Classes registry.

### What learners can expect

- Weekly live sessions with guided coding exercises.
- Practical mini-projects with mentor feedback.
- Community discussion and Q&A support.
34 changes: 33 additions & 1 deletion contentlayer.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,30 @@ const bookFields: FieldDefs = {
authorLink: { type: "string", required: false },
};

const classFields: FieldDefs = {
title: { type: "string", required: true },
description: { type: "string", required: true },
instructorName: { type: "string", required: true },
classLink: { type: "string", required: true },
tags: {
type: "list",
of: { type: "string" },
required: true,
},
classType: {
type: "enum",
options: ["online", "In-Person"],
required: true,
},
status: {
type: "enum",
options: ["active", "completed", "incoming"],
required: true,
},
proofOfAssociation: { type: "string", required: true },
image: { type: "string", required: false },
};

export const Book = defineDocumentType(() => ({
name: "Book",
filePathPattern: `./books/**/*.mdx`,
Expand All @@ -70,9 +94,17 @@ export const Book = defineDocumentType(() => ({
computedFields: computedFields,
}));

export const Class = defineDocumentType(() => ({
name: "Class",
filePathPattern: `./classes/**/*.mdx`,
fields: classFields,
contentType: "mdx",
computedFields: computedFields,
}));

export default makeSource({
contentDirPath: "./content",
documentTypes: [Blog, Profile, Book],
documentTypes: [Blog, Profile, Book, Class],
mdx: {
remarkPlugins: [remarkGfm],
rehypePlugins: [
Expand Down
2 changes: 2 additions & 0 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"nav": {
"home": "Home",
"profiles": "Profiles",
"classes": "Classes",
"books": "Books",
"editor": "Editor",
"howTo": "How to",
Expand Down Expand Up @@ -369,6 +370,7 @@
"navigate": "Navigate",
"home": "Home",
"profiles": "Profiles",
"classes": "Classes",
"books": "Books",
"profileEditor": "Profile Editor",
"blog": "Blog",
Expand Down
2 changes: 2 additions & 0 deletions messages/mm.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"nav": {
"home": "ပင်မစာမျက်နှာ",
"profiles": "ပရိုဖိုင်များ",
"classes": "သင်တန်းများ",
"books": "စာအုပ်များ",
"editor": "အယ်ဒီတာ",
"howTo": "လမ်းညွှန်",
Expand Down Expand Up @@ -369,6 +370,7 @@
"navigate": "လမ်းညွှန်",
"home": "ပင်မစာမျက်နှာ",
"profiles": "ပရိုဖိုင်များ",
"classes": "သင်တန်းများ",
"books": "စာအုပ်များ",
"profileEditor": "ပရိုဖိုင် အယ်ဒီတာ",
"blog": "ဘလော့ဂ်",
Expand Down
114 changes: 114 additions & 0 deletions src/app/classes/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import PageTransitionWrapper from "@/components/Animate/PageTransitionWrapper/PageTransitionWrapper";
import Container from "@/components/Common/Container/Container";
import SpacingDivider from "@/components/Common/SpacingDivider/SpacingDivider";
import APP_CONFIG from "@/config/config";
import { allClasses } from "contentlayer/generated";
import { Metadata } from "next";

export const metadata: Metadata = {
title: `Classes | ${APP_CONFIG.title}`,
description:
"Explore verified tech classes in Myanmar curated by the MMSWE community.",
openGraph: {
title: `Classes | ${APP_CONFIG.title}`,
description:
"Explore verified tech classes in Myanmar curated by the MMSWE community.",
images: "https://mmswe.com/images/mmswe-seo.png",
},
};

const ClassesPage = async () => {
const classes = [...allClasses].sort((a, b) => a.title.localeCompare(b.title));

return (
<PageTransitionWrapper>
<Container>
<section className="py-16">
<div className="max-w-3xl">
<p className="font-mono text-xs uppercase tracking-[0.25em] text-zinc-500">
Verified Registry
</p>
<h1 className="mt-4 font-display text-4xl font-bold text-zinc-100 sm:text-5xl">
Classes
</h1>
<p className="mt-4 max-w-2xl text-base leading-7 text-zinc-400">
A trust-first, community-curated directory of tech classes in
Myanmar. Listings are reviewed before publication.
</p>
</div>

{classes.length === 0 ? (
<div className="mt-12 rounded-3xl border border-white/10 bg-surface/50 p-8 text-zinc-300">
<h2 className="font-display text-2xl font-semibold text-zinc-100">
No classes yet
</h2>
<p className="mt-3 max-w-2xl text-sm leading-6 text-zinc-400">
Verified class listings will appear here after maintainers review
and approve class submissions.
</p>
</div>
) : (
<div className="mt-12 grid gap-4">
{classes.map((classItem) => (
<article
key={classItem._id}
className="rounded-3xl border border-white/10 bg-surface/50 p-6 transition-colors hover:border-white/20"
>
<div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
<div className="flex-1">
<div className="flex flex-wrap items-center gap-2">
<h2 className="font-display text-2xl font-semibold text-zinc-100">
{classItem.title}
</h2>
<span className="rounded-full border border-prism-cyan/30 bg-prism-cyan/10 px-3 py-1 text-xs font-medium text-prism-cyan">
{classItem.status}
</span>
<span className="rounded-full border border-white/15 px-3 py-1 text-xs font-medium text-zinc-300">
{classItem.classType}
</span>
</div>

<p className="mt-3 text-sm leading-6 text-zinc-400">
{classItem.description}
</p>

<p className="mt-3 text-sm text-zinc-300">
Instructor: {classItem.instructorName}
</p>

<div className="mt-4 flex flex-wrap gap-2">
{classItem.tags.map((tag) => (
<span
key={`${classItem._id}-${tag}`}
className="rounded-full border border-white/15 px-3 py-1 text-xs text-zinc-300"
>
{tag}
</span>
))}
</div>
</div>

<div className="flex flex-col gap-2 sm:items-end">
<a
href={classItem.classLink}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center justify-center rounded-full border border-prism-cyan/40 px-4 py-2 text-sm font-medium text-prism-cyan transition-colors hover:border-prism-cyan hover:bg-prism-cyan/10"
>
Official Link
</a>
</div>
</div>
</article>
))}
</div>
)}
</section>

<SpacingDivider size="lg" />
</Container>
</PageTransitionWrapper>
);
};

export default ClassesPage;
Loading
Loading