Monorepo และสแตก
Alternun ใช้ monorepo แบบ pnpm workspace พร้อมการ orchestration ด้วย TurboRepo
การตัดสินใจนี้ตั้งใจไว้ชัดเจน เพราะรีโพนี้มีหลายแอปที่ใช้โครงสร้างพื้นฐาน รูปแบบการยืนยันตัวตน งานแปล primitive ด้านดี ไซน์ และระบบอัตโนมัติของการออกรีลีสร่วมกัน
โครงสร้าง Workspace
พื้นผิวของแอป
apps/mobile
โค้ดเบสหลักของแอป AIRS
เทคโนโลยีหลัก:
- Expo
- Expo Router
- React 19
- React Native 0.81
- React Native Web
- Supabase JavaScript client
- WalletConnect
- Firebase
- NativeWind และระบบสไตล์ที่ยึดแนวทาง Tailwind
ทำไมจึงสำคัญ:
- โค้ดเบสเดียวรองรับทั้งรูปแบบเนทีฟบนมือถือและการส่งมอบบนเว็บ
- ตระกูลโดเมนสาธารณะของ AIRS ถูกขับเคลื่อนจากแอปนี้ผ่านชั้นโครงสร้างพื้นฐาน
apps/admin
คอนโซลแอดมินภายใน
เทคโนโลยีหลัก:
- Vite
- React 18
- React Router
- Refine
oidc-client-ts
ทำไมจึงสำคัญ:
- แยกเวิร์กโฟลว์ด้านปฏิบัติการออกจากประสบการณ์สาธารณะของ AIRS
- สามารถปรับใช้ร่วมกับ API ใน dashboard stack ได้
apps/api
บริการแบ็กเอนด์แบบกำหนดเอง
เทคโนโลยีหลัก:
- NestJS 10
- Fastify 4
- Swagger / OpenAPI
- ตัวแปลงสำหรับ AWS Lambda
ทำไมจึงสำคัญ:
- ทำให้แพลตฟอร์มมีที่สำหรับตรรกะแบ็กเอนด์เฉพาะที่ไม่ควรอยู่ในไคลเอนต์
- ปัจจุบันมีทั้ง health endpoint และ flow เชิงการเชื่อมต่อ เช่น พฤติกรรม Decap OAuth bridge
apps/docs
เว็บไซต์เอกสารสาธารณะ
เทคโนโลยีหลัก:
- Docusaurus 3
- React
- Mermaid diagrams
- การเชื่อมต่อกับ Decap CMS
oidc-client-tsสำหรับการเข้าถึงของบรรณาธิการที่มีการป้องกัน
ทำไมจึงสำคัญ:
- ให้ทั้งเอกสารสาธารณะของผลิตภัณฑ์และเอกสารสำหรับนักพัฒนา
- รองรับเวิร์กโฟลว์การแก้ไขแบบมีการป้องกัน แทนการแก้เนื้อหาใน production โดยตรง
apps/web
แอปพลิเคชัน Next.js
บทบาทปัจจุบัน:
- พื้นผิวเว็บรอง
- ไม่ใช่เป้าหมายหลักของการส่งมอบสาธารณะในโมเดล infra ปัจจุบัน
จุดนี้สำคัญสำหรับผู้ที่เพิ่งเข้ามาอ่านรีโพ เพราะเส้นทางการส่งมอบหลักของ AIRS ตอนนี้เป็น Expo-web-first ไม่ใช่ Next.js-first
แพ็กเกจที่ใช้ร่วมกัน
@alternun/auth
แพ็กเกจ wrapper ด้านการยืนยันตัวตนที่ใช้ร่วมกัน
วัตถุประสงค์:
- รวม abstraction ด้าน auth ฝั่งแอปไว้ที่เดียว
- ห่อหุ้มไลบรารี auth ต้นทางที่โครงการใช้อยู่
- เพิ่มพฤติกรรมไคลเอนต์ที่เหมาะกับมือถือ
- มีสคริปต์สนับสนุนสำหรับ SES และอีเมลรอบงาน identity/email
@alternun/ui
แพ็กเกจคอมโพเนนต์ UI ที่ใช้ร่วมกัน
วัตถุประสงค์:
- เก็บชิ้นส่วนอินเทอร์เฟซที่นำกลับมาใช้ซ้ำได้ให้อยู่นอกแอปเดียว
- รองรับการใช้ซ้ำข้ามหลายแอปเมื่อภาษาการออกแบบใกล้กัน
@alternun/i18n
แพ็กเกจแคตตาล็อกคำแปลที่ใช้ร่วมกัน
วัตถุประสงค์:
- เป็นศูนย์กลางของข้อมูล locale และตัวช่วย runtime
- ให้แอปต่าง ๆ ใช้ร่วมกันแทน การคัดลอกไฟล์คำแปลหลายชุด
packages/email-templates
ส่วนสนับสนุนการสร้างและซิงก์อีเมล
วัตถุประสงค์:
- จัดเก็บเนื้อหาอีเมลหลายภาษาที่ใช้ร่วมกัน
- รองรับระบบส่งอีเมลปลายทาง เช่น การซิงก์เทมเพลต/อีเมลของ Supabase
@alternun/infra
แพ็กเกจด้านการปรับใช้และแพลตฟอร์ม
วัตถุประสงค์:
- กำหนดทรัพยากร AWS
- ควบคุมการจับคู่โดเมนและ stage
- ดูแลการสร้าง pipeline และกลไกป้องกันการปรับใช้
- ทำหน้าที่เป็นกระดูกสันหลังด้านปฏิบัติการของ monorepo
เครื่องมือหลัก
รีโพนี้ประสานง านด้วยชุดเครื่องมือขนาดเล็กแต่มี leverage สูง:
- pnpm สำหรับจัดการแพ็กเกจใน workspace
- TurboRepo สำหรับ orchestration ของ build graph
- TypeScript ทั่วทั้ง monorepo
- ESLint และ Prettier สำหรับวินัยของโค้ด
- Husky และ lint-staged สำหรับการบังคับใช้ก่อน commit
โมเดล Build และงาน
ที่รากของรีโพ มีการทำให้คำสั่งหลักเป็นมาตรฐาน:
pnpm buildpnpm devpnpm lintpnpm type-checkpnpm test
Turbo จะประสานงานงานเหล่านี้เพื่อให้ dependency ระหว่างแพ็กเกจถูก build ตามลำดับที่ถูกต้อง
สิ่งนี้ให้จุดสมดุลที่ใช้งานได้จริงกับทีม:
- แอปแต่ละตัวสามารถพัฒนาแยกกันได้
- แพ็กเกจที่ใช้ร่วมกันยังคงนำกลับมาใช้ได้
- การเปลี่ยนแปลงแบบครอบคลุมหลายส่วนยังตร วจสอบได้จากคำสั่งชุดเดียวที่รากรีโพ
ทำไมโครงสร้างนี้จึงใช้ได้ผล
Monorepo นี้ถูกปรับให้เหมาะกับงานแบบ platform มากกว่างานแอปเดี่ยว
นั่นหมายความว่าโครงสร้างนี้ไม่ใช่เรื่อง "frontend กับ backend" เป็นหลัก แต่เน้นไปที่:
- ประสบการณ์สาธารณะ
- การปฏิบัติการภายใน
- ขอบเขตของ identity และความไว้วางใจ
- โครงสร้างพื้นฐานที่นำไป deploy ได้
- ส่วนประกอบผลิตภัณฑ์ที่ใช้ร่วมกัน
สำหรับผู้มีส่วนร่วมจากภายนอก นี่คือโมเดลความคิดที่สำคัญที่สุดที่ควรมีไว้ขณะสำรวจโค้ดเบสนี้