From 6971fc231da02fcd79031d6fdb69c90fbd7bb1ab Mon Sep 17 00:00:00 2001 From: vorpax Date: Thu, 29 Jan 2026 11:44:34 +0100 Subject: [PATCH] feat: initialize HEC IA Wiki with Docker setup, build process, and content structure - Add .dockerignore t - Create Gitea Action to build and publish image - Update Dockerfile to include build steps and health check - Revise README.md - Modify config.ts for site-specific settings - Enhance content.config.ts to define collections for events, workshops, news, and technical articles --- .dockerignore | 29 ++- .gitea/workflows/build-image.yml | 46 +++++ Dockerfile | 19 ++ README.md | 312 +++++++++++++++++++++++-------- src/config.ts | 16 +- src/content.config.ts | 92 ++++++++- 6 files changed, 425 insertions(+), 89 deletions(-) create mode 100644 .gitea/workflows/build-image.yml diff --git a/.dockerignore b/.dockerignore index 3787f2e..08a78fa 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,8 +1,27 @@ -# Ignore Astro files -*.astro +# Development files +.git/ +.gitignore +.vscode/ +.DS_Store -# Ignore node_modules directory +# Cache and temp files +.astro/ node_modules/ -# Ignore build output -dist/ \ No newline at end of file +# Build output (will be rebuilt in Docker) +dist/ + +# Environment files +.env +.env.* + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Documentation (optional - comment if needed in image) +# *.md +# !README.md \ No newline at end of file diff --git a/.gitea/workflows/build-image.yml b/.gitea/workflows/build-image.yml new file mode 100644 index 0000000..5af7561 --- /dev/null +++ b/.gitea/workflows/build-image.yml @@ -0,0 +1,46 @@ +name: Build and Push Docker Image - HEC IA Wiki + +on: + push: + branches: + - main + - master + +env: + REGISTRY: "gitea.vorpax.dev" + IMAGE_NAME: "vorpax_admin/hecia-wiki" + +jobs: + build-and-push: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Gitea Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ gitea.actor }} + password: ${{ secrets.REGISTRY_TOKEN }} + + - name: Extract metadata (tags, labels) + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=sha,prefix= + type=raw,value=latest,enable=${{ gitea.ref == format('refs/heads/{0}', 'main') || gitea.ref == format('refs/heads/{0}', 'master') }} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/Dockerfile b/Dockerfile index 6464aed..dd56eaa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,13 +5,32 @@ WORKDIR /app # Install pnpm RUN corepack enable && corepack prepare pnpm@latest --activate +# Copy package files COPY package.json pnpm-lock.yaml ./ + +# Install dependencies RUN pnpm install --frozen-lockfile +# Copy all source files (respecting .dockerignore) COPY . . + +# Build the application +# Note: The build script includes: astro check && astro build && pagefind --site dist && cp -r dist/pagefind public/ RUN pnpm run build # Runtime stage for serving the application FROM nginx:mainline-alpine-slim AS runtime + +# Copy the built site from dist directory COPY --from=base /app/dist /usr/share/nginx/html + +# The build script copies pagefind to public/, so we need to copy it back to dist for the runtime +# Copy pagefind if it exists in public/ +COPY --from=base /app/public/pagefind /usr/share/nginx/html/pagefind + +# Expose port 80 EXPOSE 80 + +# Add healthcheck +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost/ || exit 1 diff --git a/README.md b/README.md index 916326f..f8cdfc6 100644 --- a/README.md +++ b/README.md @@ -1,72 +1,234 @@ -# AstroPaper 📄 +# HEC IA Wiki 🤖 -![AstroPaper](public/astropaper-og.jpg) -[![Figma](https://img.shields.io/badge/Figma-F24E1E?style=for-the-badge&logo=figma&logoColor=white)](https://www.figma.com/community/file/1356898632249991861) -![Typescript](https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge&logo=typescript&logoColor=white) -![GitHub](https://img.shields.io/github/license/satnaing/astro-paper?color=%232F3741&style=for-the-badge) -[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-%23FE5196?logo=conventionalcommits&logoColor=white&style=for-the-badge)](https://conventionalcommits.org) -[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg?style=for-the-badge)](http://commitizen.github.io/cz-cli/) +![HEC IA Wiki](public/hec-ia-og.jpg) -AstroPaper is a minimal, responsive, accessible and SEO-friendly Astro blog theme. This theme is designed and crafted based on [my personal blog](https://satnaing.dev/blog). +The official wiki and knowledge base for HEC IA student association. Built with [Astro](https://astro.build/) and the [AstroPaper](https://github.com/satnaing/astro-paper) theme. -Read [the blog posts](https://astro-paper.pages.dev/posts/) or check [the README Documentation Section](#-documentation) for more info. +## 📚 About -## 🔥 Features +This wiki serves as a central hub for HEC IA's content, including: -- [x] type-safe markdown -- [x] super fast performance -- [x] accessible (Keyboard/VoiceOver) -- [x] responsive (mobile ~ desktops) -- [x] SEO-friendly -- [x] light & dark mode -- [x] fuzzy search -- [x] draft posts & pagination -- [x] sitemap & rss feed -- [x] followed best practices -- [x] highly customizable -- [x] dynamic OG image generation for blog posts [#15](https://github.com/satnaing/astro-paper/pull/15) ([Blog Post](https://astro-paper.pages.dev/posts/dynamic-og-image-generation-in-astropaper-blog-posts/)) +- **Events**: Information about upcoming and past events +- **Workshops**: Hands-on technical workshops and tutorials +- **News**: Latest updates and announcements from HEC IA +- **Technical Deep Dives**: In-depth technical articles on AI topics -_Note: I've tested screen-reader accessibility of AstroPaper using **VoiceOver** on Mac and **TalkBack** on Android. I couldn't test all other screen-readers out there. However, accessibility enhancements in AstroPaper should be working fine on others as well._ +## 🚀 Quick Start -## ✅ Lighthouse Score +### Prerequisites -

- - AstroPaper Lighthouse Score - -

+- Node.js 18+ +- npm or pnpm -## 🚀 Project Structure +### Installation -Inside of AstroPaper, you'll see the following folders and files: +```bash +# Clone the repository +git clone https://github.com/hec-ia/wiki.git +cd wiki + +# Install dependencies +npm install + +# Start development server +npm run dev +``` + +The site will be available at `http://localhost:4321` + +### Building for Production + +```bash +# Build the site +npm run build + +# Preview the build +npm run preview +``` + +## 📝 Adding Content + +### Events + +Create a new markdown file in `src/data/events/`: + +```markdown +--- +title: "Your Event Title" +description: "Event description" +author: "HEC IA" +pubDatetime: 2026-01-15T10:00:00Z +eventDate: 2026-02-05T14:00:00Z +eventEndDate: 2026-02-05T18:00:00Z +location: "Event Location" +tags: ["tag1", "tag2"] +featured: true +registrationLink: "https://registration-link.com" +--- + +Your event content here... +``` + +### Workshops + +Create a new markdown file in `src/data/workshops/`: + +```markdown +--- +title: "Workshop Title" +description: "Workshop description" +author: "HEC IA" +pubDatetime: 2026-01-15T10:00:00Z +workshopDate: 2026-02-05T14:00:00Z +duration: "3 hours" +level: "beginner" # beginner, intermediate, or advanced +tags: ["machine-learning", "python"] +featured: true +materials: "https://github.com/hec-ia/workshop-materials" +--- + +Your workshop content here... +``` + +### News + +Create a new markdown file in `src/data/news/`: + +```markdown +--- +title: "News Title" +description: "News description" +author: "HEC IA" +pubDatetime: 2026-01-25T10:00:00Z +tags: ["news", "announcement"] +featured: true +--- + +Your news content here... +``` + +### Technical Deep Dives + +Create a new markdown file in `src/data/technical/`: + +```markdown +--- +title: "Technical Article Title" +description: "Article description" +author: "HEC IA Technical Team" +pubDatetime: 2026-01-28T10:00:00Z +tags: ["deep-learning", "nlp"] +difficulty: "advanced" # beginner, intermediate, or advanced +readingTime: "25 min" +featured: true +--- + +Your technical content here... +``` + +## 🎨 Customization + +### Site Configuration + +Edit `src/config.ts` to customize: + +- Site title and description +- Author information +- Social links +- Posts per page +- And more... + +### Theme Colors + +The site uses Tailwind CSS. Customize colors in: + +- `src/styles/base.css` for global styles +- `tailwind.config.js` for theme configuration + +## 📂 Project Structure ```bash / ├── public/ -│ ├── pagefind/ # auto-generated when build -│ ├── favicon.svg -│ └── astropaper-og.jpg +│ └── assets/ # Static assets ├── src/ -│ ├── assets/ -│ │ ├── icons/ -│ │ └── images/ -│ ├── components/ -│ ├── data/ -│ │ └── blog/ -│ │ └── some-blog-posts.md -│ ├── layouts/ -│ ├── pages/ -│ ├── scripts/ -│ ├── styles/ -│ ├── utils/ -│ ├── config.ts -│ ├── constants.ts -│ ├── content.config.ts -│ ├── env.d.ts -│ └── remark-collapse.d.ts -└── astro.config.ts +│ ├── assets/ # SVG icons and images +│ ├── components/ # Astro components +│ ├── data/ # Content collections +│ │ ├── events/ +│ │ ├── workshops/ +│ │ ├── news/ +│ │ └── technical/ +│ ├── layouts/ # Page layouts +│ ├── pages/ # Route pages +│ ├── styles/ # Global styles +│ ├── utils/ # Utility functions +│ ├── config.ts # Site configuration +│ └── content.config.ts # Content collections config +├── astro.config.ts +├── package.json +└── README.md ``` +## 🧞 Available Commands + +| Command | Action | +| :--------------------- | :----------------------------------------------- | +| `npm install` | Installs dependencies | +| `npm run dev` | Starts local dev server at `localhost:4321` | +| `npm run build` | Build your production site to `./dist/` | +| `npm run preview` | Preview your build locally, before deploying | +| `npm run format:check` | Check code format with Prettier | +| `npm run format` | Format codes with Prettier | +| `npm run sync` | Generates TypeScript types for all Astro modules | +| `npm run lint` | Lint with ESLint | + +## 🤝 Contributing + +Contributions are welcome! Please feel free to submit a Pull Request. + +1. Fork the repository +2. Create your feature branch (`git checkout -b feature/AmazingFeature`) +3. Commit your changes (`git commit -m 'Add some AmazingFeature'`) +4. Push to the branch (`git push origin feature/AmazingFeature`) +5. Open a Pull Request + +## 📄 License + +This project is licensed under the MIT License - see the LICENSE file for details. + +## 🙏 Acknowledgments + +Built with: + +- [Astro](https://astro.build/) - The web framework for content-driven websites +- [AstroPaper](https://github.com/satnaing/astro-paper) - The base theme +- [Tailwind CSS](https://tailwindcss.com/) - For styling +- [TypeScript](https://www.typescriptlang.org/) - For type safety + +--- + +Made with ❤️ by HEC IA +│ │ ├── icons/ +│ │ └── images/ +│ ├── components/ +│ ├── data/ +│ │ └── blog/ +│ │ └── some-blog-posts.md +│ ├── layouts/ +│ ├── pages/ +│ ├── scripts/ +│ ├── styles/ +│ ├── utils/ +│ ├── config.ts +│ ├── constants.ts +│ ├── content.config.ts +│ ├── env.d.ts +│ └── remark-collapse.d.ts +└── astro.config.ts + +```` + Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. Any static assets, like images, can be placed in the `public/` directory. @@ -84,15 +246,15 @@ Documentation can be read in two formats\_ _markdown_ & _blog post_. ## 💻 Tech Stack -**Main Framework** - [Astro](https://astro.build/) -**Type Checking** - [TypeScript](https://www.typescriptlang.org/) -**Styling** - [TailwindCSS](https://tailwindcss.com/) -**UI/UX** - [Figma Design File](https://www.figma.com/community/file/1356898632249991861) -**Static Search** - [FuseJS](https://pagefind.app/) -**Icons** - [Tablers](https://tabler-icons.io/) -**Code Formatting** - [Prettier](https://prettier.io/) -**Deployment** - [Cloudflare Pages](https://pages.cloudflare.com/) -**Illustration in About Page** - [https://freesvgillustration.com](https://freesvgillustration.com/) +**Main Framework** - [Astro](https://astro.build/) +**Type Checking** - [TypeScript](https://www.typescriptlang.org/) +**Styling** - [TailwindCSS](https://tailwindcss.com/) +**UI/UX** - [Figma Design File](https://www.figma.com/community/file/1356898632249991861) +**Static Search** - [FuseJS](https://pagefind.app/) +**Icons** - [Tablers](https://tabler-icons.io/) +**Code Formatting** - [Prettier](https://prettier.io/) +**Deployment** - [Cloudflare Pages](https://pages.cloudflare.com/) +**Illustration in About Page** - [https://freesvgillustration.com](https://freesvgillustration.com/) **Linting** - [ESLint](https://eslint.org) ## 👨🏻‍💻 Running Locally @@ -111,7 +273,7 @@ yarn create astro --template satnaing/astro-paper # bun bun create astro@latest -- --template satnaing/astro-paper -``` +```` Then start the project by running the following commands: @@ -150,20 +312,20 @@ All commands are run from the root of the project, from a terminal: > **_Note!_** For `Docker` commands we must have it [installed](https://docs.docker.com/engine/install/) in your machine. -| Command | Action | -| :----------------------------------- | :------------------------------------------------------------------------------------------------------------------------------- | -| `pnpm install` | Installs dependencies | -| `pnpm run dev` | Starts local dev server at `localhost:4321` | -| `pnpm run build` | Build your production site to `./dist/` | -| `pnpm run preview` | Preview your build locally, before deploying | -| `pnpm run format:check` | Check code format with Prettier | -| `pnpm run format` | Format codes with Prettier | -| `pnpm run sync` | Generates TypeScript types for all Astro modules. [Learn more](https://docs.astro.build/en/reference/cli-reference/#astro-sync). | -| `pnpm run lint` | Lint with ESLint | -| `docker compose up -d` | Run AstroPaper on docker, You can access with the same hostname and port informed on `dev` command. | +| Command | Action | +| :------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------- | +| `pnpm install` | Installs dependencies | +| `pnpm run dev` | Starts local dev server at `localhost:4321` | +| `pnpm run build` | Build your production site to `./dist/` | +| `pnpm run preview` | Preview your build locally, before deploying | +| `pnpm run format:check` | Check code format with Prettier | +| `pnpm run format` | Format codes with Prettier | +| `pnpm run sync` | Generates TypeScript types for all Astro modules. [Learn more](https://docs.astro.build/en/reference/cli-reference/#astro-sync). | +| `pnpm run lint` | Lint with ESLint | +| `docker compose up -d` | Run AstroPaper on docker, You can access with the same hostname and port informed on `dev` command. | | `docker compose run app pnpm install` | You can run any command above into the docker container. | -| `docker build -t astropaper .` | Build Docker image for AstroPaper. | -| `docker run -p 4321:80 astropaper` | Run AstroPaper on Docker. The website will be accessible at `http://localhost:4321`. | +| `docker build -t astropaper .` | Build Docker image for AstroPaper. | +| `docker run -p 4321:80 astropaper` | Run AstroPaper on Docker. The website will be accessible at `http://localhost:4321`. | > **_Warning!_** Windows PowerShell users may need to install the [concurrently package](https://www.npmjs.com/package/concurrently) if they want to [run diagnostics](https://docs.astro.build/en/reference/cli-reference/#astro-check) during development (`astro check --watch & astro dev`). For more info, see [this issue](https://github.com/satnaing/astro-paper/issues/113). diff --git a/src/config.ts b/src/config.ts index b4a219f..66a0f02 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,10 +1,10 @@ export const SITE = { - website: "https://astro-paper.pages.dev/", // replace this with your deployed domain - author: "Sat Naing", - profile: "https://satnaing.dev/", - desc: "A minimal, responsive and SEO-friendly Astro blog theme.", - title: "AstroPaper", - ogImage: "astropaper-og.jpg", + website: "https://wiki.hec-ia.com/", // replace this with your deployed domain + author: "HEC IA", + profile: "https://wiki.hec-ia.com/about", + desc: "HEC IA student association wiki - Events, workshops, news, and technical deep dives on artificial intelligence.", + title: "HEC IA Wiki", + ogImage: "hec-ia-og.jpg", lightAndDarkMode: true, postPerIndex: 4, postPerPage: 4, @@ -14,10 +14,10 @@ export const SITE = { editPost: { enabled: true, text: "Edit page", - url: "https://github.com/satnaing/astro-paper/edit/main/", + url: "https://github.com/hec-ia/wiki/edit/main/", }, dynamicOgImage: true, dir: "ltr", // "rtl" | "auto" lang: "en", // html lang code. Set this empty and default will be "en" - timezone: "Asia/Bangkok", // Default global timezone (IANA format) https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + timezone: "Europe/Paris", // Default global timezone (IANA format) https://en.wikipedia.org/wiki/List_of_tz_database_time_zones } as const; diff --git a/src/content.config.ts b/src/content.config.ts index 6119aa6..4d46415 100644 --- a/src/content.config.ts +++ b/src/content.config.ts @@ -3,6 +3,10 @@ import { glob } from "astro/loaders"; import { SITE } from "@/config"; export const BLOG_PATH = "src/data/blog"; +export const EVENTS_PATH = "src/data/events"; +export const WORKSHOPS_PATH = "src/data/workshops"; +export const NEWS_PATH = "src/data/news"; +export const TECHNICAL_PATH = "src/data/technical"; const blog = defineCollection({ loader: glob({ pattern: "**/[^_]*.md", base: `./${BLOG_PATH}` }), @@ -23,4 +27,90 @@ const blog = defineCollection({ }), }); -export const collections = { blog }; +const events = defineCollection({ + loader: glob({ pattern: "**/[^_]*.md", base: `./${EVENTS_PATH}` }), + schema: ({ image }) => + z.object({ + author: z.string().default(SITE.author), + pubDatetime: z.date(), + eventDate: z.date(), + eventEndDate: z.date().optional(), + location: z.string().optional(), + modDatetime: z.date().optional().nullable(), + title: z.string(), + featured: z.boolean().optional(), + draft: z.boolean().optional(), + tags: z.array(z.string()).default(["event"]), + ogImage: image().or(z.string()).optional(), + description: z.string(), + canonicalURL: z.string().optional(), + hideEditPost: z.boolean().optional(), + timezone: z.string().optional(), + registrationLink: z.string().optional(), + }), +}); + +const workshops = defineCollection({ + loader: glob({ pattern: "**/[^_]*.md", base: `./${WORKSHOPS_PATH}` }), + schema: ({ image }) => + z.object({ + author: z.string().default(SITE.author), + pubDatetime: z.date(), + workshopDate: z.date(), + duration: z.string().optional(), + level: z.enum(["beginner", "intermediate", "advanced"]).optional(), + modDatetime: z.date().optional().nullable(), + title: z.string(), + featured: z.boolean().optional(), + draft: z.boolean().optional(), + tags: z.array(z.string()).default(["workshop"]), + ogImage: image().or(z.string()).optional(), + description: z.string(), + canonicalURL: z.string().optional(), + hideEditPost: z.boolean().optional(), + timezone: z.string().optional(), + materials: z.string().optional(), + }), +}); + +const news = defineCollection({ + loader: glob({ pattern: "**/[^_]*.md", base: `./${NEWS_PATH}` }), + schema: ({ image }) => + z.object({ + author: z.string().default(SITE.author), + pubDatetime: z.date(), + modDatetime: z.date().optional().nullable(), + title: z.string(), + featured: z.boolean().optional(), + draft: z.boolean().optional(), + tags: z.array(z.string()).default(["news"]), + ogImage: image().or(z.string()).optional(), + description: z.string(), + canonicalURL: z.string().optional(), + hideEditPost: z.boolean().optional(), + timezone: z.string().optional(), + }), +}); + +const technical = defineCollection({ + loader: glob({ pattern: "**/[^_]*.md", base: `./${TECHNICAL_PATH}` }), + schema: ({ image }) => + z.object({ + author: z.string().default(SITE.author), + pubDatetime: z.date(), + modDatetime: z.date().optional().nullable(), + title: z.string(), + featured: z.boolean().optional(), + draft: z.boolean().optional(), + tags: z.array(z.string()).default(["technical"]), + ogImage: image().or(z.string()).optional(), + description: z.string(), + canonicalURL: z.string().optional(), + hideEditPost: z.boolean().optional(), + timezone: z.string().optional(), + difficulty: z.enum(["beginner", "intermediate", "advanced"]).optional(), + readingTime: z.string().optional(), + }), +}); + +export const collections = { blog, events, workshops, news, technical };