188 lines
5.8 KiB
Markdown
188 lines
5.8 KiB
Markdown
# Nicholai's website
|
|
|
|
This is my personal website built with Next.js 15, Tailwind CSS, and TypeScript.
|
|
|
|
## Tech Stack
|
|
|
|
Next.js 15, Tailwind CSS, Cabin font family, Turbopack, Typescript.
|
|
|
|
### Prerequisites
|
|
|
|
- Node.js 18+ installed (node modules: densest thing in the known universe.)
|
|
- npm, yarn, pnpm, whatever honestly.
|
|
|
|
### Installation
|
|
|
|
1. Clone the repository:
|
|
```bash
|
|
git clone https://git.biohazardvfx.com/Nicholai/nicholais-website.git
|
|
```
|
|
|
|
2. Install dependencies:
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
### Development
|
|
|
|
Run the development server:
|
|
|
|
```bash
|
|
npm run dev
|
|
# or
|
|
yarn dev
|
|
# or
|
|
pnpm dev
|
|
# or
|
|
bun dev
|
|
```
|
|
|
|
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
|
|
|
### Pushing to Git and Docker
|
|
|
|
1. Commit changed files to main branch on gitea
|
|
`git add . && git commit -m "added higher res profile image" && git push origin main`
|
|
|
|
2. Build docker image
|
|
`docker build -t git.biohazardvfx.com/nicholai/nicholais-website:latest .`
|
|
|
|
3. Push docker package to gitea
|
|
`docker push git.biohazardvfx.com/nicholai/nicholais-website:latest`
|
|
|
|
### Building for Production
|
|
|
|
```bash
|
|
npm run build
|
|
```
|
|
|
|
### Deployment
|
|
|
|
#### Docker Deployment
|
|
|
|
This project includes a Dockerfile for containerized deployment. To build and run the application using Docker:
|
|
|
|
1. Build the image:
|
|
```bash
|
|
docker build -t nicholais-website .
|
|
```
|
|
|
|
2. Run the container:
|
|
```bash
|
|
docker run -p 3000:3000 nicholais-website
|
|
```
|
|
|
|
3. Or with environment variables:
|
|
```bash
|
|
docker run -p 3000:3000 -e NODE_ENV=production nicholais-website
|
|
```
|
|
|
|
#### Environment Variables
|
|
|
|
The application supports the following environment variables:
|
|
|
|
| Variable | Description | Default |
|
|
|----------|-------------|---------|
|
|
| `NODE_ENV` | Node.js environment | `development` |
|
|
| `PORT` | Port to run the server on | `3000` |
|
|
|
|
### Blog Authoring (MDX)
|
|
|
|
You can write posts in MDX and have them show up on `/blog`.
|
|
|
|
- Local posts: add `.mdx` files to `app/blog/posts/` (these are always included).
|
|
- Optional GitHub-backed posts: if you configure the `BLOG_*` environment variables, MDX files from your GitHub repo are fetched and merged with local posts. GitHub posts override local ones on duplicate slugs.
|
|
|
|
Setup:
|
|
1) Copy `.env.local.example` to `.env.local` and fill in values.
|
|
2) For GitHub-backed content, set:
|
|
- `BLOG_REPO=owner/repo`
|
|
- `BLOG_PATH=path/to/mdx/folder` (relative to repo root)
|
|
- `BLOG_BRANCH=main` (or your branch)
|
|
- `GITHUB_TOKEN=` (only required for private repos or higher rate limits)
|
|
|
|
Frontmatter template (put at the top of each `.mdx` file):
|
|
```md
|
|
---
|
|
title: "Post Title"
|
|
publishedAt: "2025-01-15" # YYYY-MM-DD
|
|
summary: "One-liner summary"
|
|
tags: ["tag1", "tag2"]
|
|
image: "https://your.cdn/path-or-absolute-url.jpg"
|
|
---
|
|
```
|
|
|
|
Images:
|
|
- Prefer absolute URLs (CDN or repo raw URLs) to avoid build-time asset issues.
|
|
- The MDX renderer handles links and images for you (see `components/mdx.tsx`).
|
|
|
|
How updates appear on the site:
|
|
- Incremental Static Regeneration (ISR): GitHub responses are cached with `next: { revalidate: BLOG_REVALIDATE_SECONDS }`. New/edited posts appear automatically after the configured window (default 300s).
|
|
- On-demand revalidation: trigger an immediate refresh via the `/api/revalidate` endpoint (see below) or configure a GitHub webhook to call it on each push.
|
|
|
|
### Blog Environment Variables
|
|
|
|
| Variable | Description | Default |
|
|
|----------|-------------|---------|
|
|
| `BLOG_REPO` | GitHub `owner/repo` containing your MDX files. Leave empty to use only local posts. | — |
|
|
| `BLOG_PATH` | Path in the repo where `.mdx` files live (relative to repo root). | `app/blog/posts` |
|
|
| `BLOG_BRANCH` | Branch name to read from. | `main` |
|
|
| `GITHUB_TOKEN` | GitHub token. Required for private repos or higher rate limits. | — |
|
|
| `BLOG_REVALIDATE_SECONDS` | ISR interval (seconds) for GitHub fetch cache. | `300` |
|
|
| `BLOG_CACHE_TAG` | Cache tag used for on-demand invalidation (`revalidateTag`). | `blog-content` |
|
|
| `REVALIDATE_SECRET` | Shared secret for the revalidate API and GitHub webhook signature. | — |
|
|
|
|
### On-demand Revalidation
|
|
|
|
An API route at `/api/revalidate` invalidates the blog listing and post pages, and also busts the cache tag used for GitHub content.
|
|
|
|
- GET (simple manual trigger):
|
|
- Revalidate listing:
|
|
```bash
|
|
curl -sS "https://your-domain/api/revalidate?secret=REVALIDATE_SECRET"
|
|
```
|
|
- Revalidate a specific post (by slug):
|
|
```bash
|
|
curl -sS "https://your-domain/api/revalidate?secret=REVALIDATE_SECRET&slug=my-post-slug"
|
|
```
|
|
- Optionally revalidate additional paths:
|
|
```bash
|
|
curl -sS "https://your-domain/api/revalidate?secret=REVALIDATE_SECRET&path=/blog/my-post-slug"
|
|
```
|
|
|
|
- POST (advanced, supports multiple slugs/paths):
|
|
```bash
|
|
curl -sS -X POST "https://your-domain/api/revalidate" \
|
|
-H "x-revalidate-secret: REVALIDATE_SECRET" \
|
|
-H "content-type: application/json" \
|
|
-d '{
|
|
"slugs": ["my-post-slug"],
|
|
"paths": ["/blog", "/blog/my-post-slug"]
|
|
}'
|
|
```
|
|
|
|
- GitHub Webhook (recommended):
|
|
1) In your repo settings, add a Webhook:
|
|
- Payload URL: `https://your-domain/api/revalidate`
|
|
- Content type: `application/json`
|
|
- Secret: set to the same value as `REVALIDATE_SECRET`
|
|
- Event: “Just the push event”
|
|
2) On push, the webhook sends changed file paths. The API will:
|
|
- Revalidate the `BLOG_CACHE_TAG` to refresh GitHub fetches.
|
|
- Revalidate `/blog` and any changed post slugs under `BLOG_PATH`.
|
|
|
|
Security notes:
|
|
- Do not expose `REVALIDATE_SECRET` publicly. For manual GET usage, keep the URL private.
|
|
- For CI/CD, use the POST form with the `x-revalidate-secret` header.
|
|
|
|
## License
|
|
|
|
This project is open source, take it. I don't give a fuck. I am not your dad.
|
|
|
|
## Author
|
|
|
|
Nicholai - VFX Supervisor & Developer
|
|
- Website: [nicholai.work](https://nicholai.work)
|
|
- Email: nicholai@biohazardvfx.com
|
|
- Instagram: [@nicholai.exe](https://www.instagram.com/nicholai.exe/)
|