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 🤖
-
-[](https://www.figma.com/community/file/1356898632249991861)
-
-
-[](https://conventionalcommits.org)
-[](http://commitizen.github.io/cz-cli/)
+
-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
-
-
-
-
-
+- 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 };