7 Commits

Author SHA1 Message Date
RJ
d349c1a957 Update nextjs to version 16.0.7
All checks were successful
Build and Deploy Next.js Blog to Staging / 🔍 Code Quality Checks (push) Successful in 26s
Build and Deploy Next.js Blog to Staging / 🏗️ Build and Push Docker Image (push) Successful in 44s
Build and Deploy Next.js Blog to Staging / 🚀 Deploy to Staging (push) Successful in 48s
Build and Deploy Next.js Blog to Production / 🔍 Code Quality Checks (push) Successful in 17s
Build and Deploy Next.js Blog to Production / 🏗️ Build and Push Docker Image (push) Successful in 4s
Build and Deploy Next.js Blog to Production / 🚀 Deploy to Production (push) Successful in 47s
PR Checks / lint-and-build (pull_request) Successful in 18s
2025-12-04 07:41:13 +00:00
RJ
0e0c21449b 🚨 update translation
All checks were successful
Build and Deploy Next.js Blog to Staging / 🔍 Code Quality Checks (push) Successful in 17s
Build and Deploy Next.js Blog to Staging / 🏗️ Build and Push Docker Image (push) Successful in 35s
PR Checks / lint-and-build (pull_request) Successful in 21s
Build and Deploy Next.js Blog to Staging / 🚀 Deploy to Staging (push) Successful in 48s
2025-12-03 17:51:34 +02:00
RJ
73cbc8f731 🟢 pr check on any opened pr
All checks were successful
Build and Deploy Next.js Blog to Staging / 🔍 Code Quality Checks (push) Successful in 23s
PR Checks / lint-and-build (pull_request) Successful in 22s
Build and Deploy Next.js Blog to Staging / 🏗️ Build and Push Docker Image (push) Successful in 32s
Build and Deploy Next.js Blog to Staging / 🚀 Deploy to Staging (push) Successful in 48s
Build and Deploy Next.js Blog to Production / 🔍 Code Quality Checks (push) Successful in 18s
Build and Deploy Next.js Blog to Production / 🏗️ Build and Push Docker Image (push) Successful in 3s
Build and Deploy Next.js Blog to Production / 🚀 Deploy to Production (push) Successful in 47s
2025-12-03 16:34:39 +02:00
RJ
77b4e95a93 🚨 add pr checks 2025-12-03 16:33:43 +02:00
RJ
fd50757c94 📄 update staging pipeline script 2025-12-03 16:33:43 +02:00
RJ
7e8b82f571 📄 Huge intl feature 2025-12-03 16:33:43 +02:00
RJ
8b05aae5a8 🏗️ add staging CICD and env 2025-12-03 16:33:43 +02:00
7 changed files with 757 additions and 256 deletions

View File

@@ -0,0 +1,34 @@
name: PR Checks
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
jobs:
lint-and-build:
runs-on: node-22
steps:
- name: Checkout
uses: actions/checkout@v4
- name: 📥 Install dependencies
run: npm ci
- name: 🔍 Run ESLint
run: npm run lint
continue-on-error: true
- name: 💅 Check code formatting (Prettier)
run: npm run format:check
continue-on-error: true
- name: 🔤 TypeScript type checking
run: npx tsc --noEmit
- name: ✅ All quality checks passed
run: |
echo "✅ All code quality checks passed successfully!"
echo " - ESLint: No linting errors"
echo " - Prettier: Code is properly formatted"
echo " - TypeScript: No type errors"

View File

@@ -0,0 +1,384 @@
# Gitea Actions Workflow for Next.js Blog Application - Staging Environment
# This workflow builds a Docker image and deploys it to staging
#
# Workflow triggers:
# - Push to staging branch (automatic deployment)
# - Manual trigger via workflow_dispatch
#
# Required Secrets (configure in Gitea repository settings):
# - PRODUCTION_HOST: IP address or hostname of production server (same server hosts staging)
# - PRODUCTION_USER: SSH username (e.g., 'deployer')
# - SSH_PRIVATE_KEY: Private SSH key for authentication
#
# Environment Variables (configured below):
# - REGISTRY: Docker registry URL
# - IMAGE_NAME: Docker image name
#
# Docker Registry Configuration:
# - Current registry (repository.workspace:5000) is INSECURE - no authentication required
# - Registry login steps are SKIPPED to avoid 7+ minute timeout delays
# - Docker push/pull operations work without credentials
# - If switching to authenticated registry: uncomment login steps and configure secrets
name: Build and Deploy Next.js Blog to Staging
on:
push:
branches:
- staging # Trigger on push to staging branch
workflow_dispatch: # Allow manual trigger from Gitea UI
env:
# Docker registry configuration
# Update this to match your private registry URL
REGISTRY: repository.workspace:5000
IMAGE_NAME: mypage
jobs:
# ============================================
# Job 1: Code Quality Checks (Linting)
# ============================================
lint:
name: 🔍 Code Quality Checks
runs-on: node-22
# env:
# ACTIONS_RUNTIME_URL: http://192.168.1.53:3000 # Setează la nivel de job
steps:
- name: 🔎 Checkout code
uses: actions/checkout@v4
# with:
# github-server-url: ${{ env.ACTIONS_RUNTIME_URL }}
# - name: 📦 Setup Node.js
# uses: actions/setup-node@v4
# with:
# node-version: "22"
# cache: "npm"
- name: 📥 Install dependencies
run: npm ci
- name: 🔍 Run ESLint
run: npm run lint
continue-on-error: true
- name: 💅 Check code formatting (Prettier)
run: npm run format:check
continue-on-error: true
- name: 🔤 TypeScript type checking
run: npx tsc --noEmit
- name: ✅ All quality checks passed
run: |
echo "✅ All code quality checks passed successfully!"
echo " - ESLint: No linting errors"
echo " - Prettier: Code is properly formatted"
echo " - TypeScript: No type errors"
# ============================================
# Job 2: Build and Push Docker Image
# ============================================
build-and-push:
name: 🏗️ Build and Push Docker Image
runs-on: ubuntu-latest
needs: [lint] # Wait for lint job to complete successfully
steps:
- name: 🔎 Checkout code
uses: actions/checkout@v4
- name: 📝 Create .env file from Gitea secrets
run: |
echo "Creating .env file for Docker build..."
cat > .env << EOF
# Build-time environment variables
NEXT_PUBLIC_SITE_URL=${{ vars.NEXT_PUBLIC_SITE_URL }}
NODE_ENV=production
NEXT_TELEMETRY_DISABLED=1
# Add other build-time variables here as needed
# NEXT_PUBLIC_GA_ID=${{ vars.NEXT_PUBLIC_GA_ID }}
EOF
echo "✅ .env file created successfully"
echo "Preview (secrets masked):"
cat .env | sed 's/=.*/=***MASKED***/g'
# Insecure registry configuration - no authentication required
# The registry at repository.workspace:5000 does not require login
# Docker push/pull operations work without credentials
- name: Registry configuration (insecure - no login required)
run: |
echo "=== Docker Registry Configuration ==="
echo "Registry: ${{ env.REGISTRY }}"
echo "Type: Insecure (no authentication required)"
echo ""
echo " Skipping registry login - insecure registry allows push/pull without credentials"
echo ""
echo "If your registry requires authentication in the future:"
echo " 1. Set REGISTRY_USERNAME and REGISTRY_PASSWORD secrets in Gitea"
echo " 2. Uncomment the login step below this message"
echo " 3. Change registry URL to authenticated registry"
# Uncomment this step if registry requires authentication in the future
# - name: 🔐 Log in to Docker Registry
# timeout-minutes: 1
# run: |
# if [ -n "${{ secrets.REGISTRY_USERNAME }}" ] && [ -n "${{ secrets.REGISTRY_PASSWORD }}" ]; then
# echo "Attempting login to ${{ env.REGISTRY }}..."
# timeout 30s bash -c 'echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin' || {
# echo "⚠️ Login failed - continuing anyway"
# }
# fi
- name: 🏗️ Build Docker image
timeout-minutes: 30
env:
DOCKER_BUILDKIT: 1 # Enable BuildKit for faster builds and better caching
run: |
echo "Building Next.js Docker image with BuildKit (staging)..."
echo "Build context size:"
du -sh . 2>/dev/null || echo "Cannot measure context size"
# Build the Docker image for staging
# - Uses Dockerfile.nextjs from project root
# - Tags image with 'staging' tag
# - Enables inline cache for faster subsequent builds
docker build \
--progress=plain \
--build-arg BUILDKIT_INLINE_CACHE=1 \
-t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:staging \
-f Dockerfile.nextjs \
.
echo "✅ Build successful"
echo "Image size:"
docker images ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:staging
- name: 🚀 Push Docker image to registry
run: |
echo "Pushing staging image to registry..."
# Push staging tag
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:staging
echo "✅ Image pushed successfully"
echo " - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:staging"
# ============================================
# Job 3: Deploy to Staging Server
# ============================================
deploy-staging:
name: 🚀 Deploy to Staging
runs-on: ubuntu-latest
needs: [build-and-push] # Wait for build job to complete
environment:
name: staging
url: http://192.168.1.54:3031
steps:
- name: 🔎 Checkout code (for docker-compose file)
uses: actions/checkout@v4
# Verify Docker is accessible on staging server
# Registry authentication is not required for insecure registry
- name: Verify staging server Docker access
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ vars.PRODUCTION_HOST }}
username: ${{ vars.PRODUCTION_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: 22
script: |
echo "=== Verifying Docker is accessible ==="
docker info > /dev/null 2>&1 || {
echo "❌ Docker is not running or user has no access"
echo "Please ensure Docker is installed and user is in docker group"
exit 1
}
echo "✅ Docker is accessible"
echo ""
echo "=== Registry Configuration ==="
echo "Registry: ${{ env.REGISTRY }}"
echo "Type: Insecure (no authentication)"
echo " Skipping registry login - push/pull will work without credentials"
- name: 📁 Ensure staging directory structure
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ vars.PRODUCTION_HOST }}
username: ${{ vars.PRODUCTION_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: 22
script: |
echo "=== Ensuring staging directory structure ==="
# Verify base directory exists and is writable
# Update /opt/mypage-staging to match your deployment directory
if [ ! -d /opt/mypage-staging ]; then
echo "❌ /opt/mypage-staging does not exist!"
echo "Please run manually on staging server:"
echo " sudo mkdir -p /opt/mypage-staging"
echo " sudo chown -R deployer:docker /opt/mypage-staging"
echo " sudo chmod -R 775 /opt/mypage-staging"
exit 1
fi
if [ ! -w /opt/mypage-staging ]; then
echo "❌ /opt/mypage-staging is not writable by $USER user"
echo "Please run manually on staging server:"
echo " sudo chown -R deployer:docker /opt/mypage-staging"
echo " sudo chmod -R 775 /opt/mypage-staging"
exit 1
fi
# Create data directories for logs
mkdir -p /opt/mypage-staging/data/logs || { echo "❌ Failed to create logs directory"; exit 1; }
echo "✅ Directory structure ready"
ls -la /opt/mypage-staging
- name: 📦 Copy docker-compose.staging.yml to staging server
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ vars.PRODUCTION_HOST }}
username: ${{ vars.PRODUCTION_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: 22
source: "docker-compose.staging.yml"
target: "/opt/mypage-staging/"
overwrite: true
- name: 🐳 Deploy application via Docker Compose
uses: appleboy/ssh-action@v1.0.3
env:
# Optional: only needed if registry requires authentication
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD || '' }}
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME || '' }}
REGISTRY_URL: ${{ env.REGISTRY }}
IMAGE_FULL: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:staging
with:
host: ${{ vars.PRODUCTION_HOST }}
username: ${{ vars.PRODUCTION_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: 22
envs: REGISTRY_PASSWORD,REGISTRY_USERNAME,REGISTRY_URL,IMAGE_FULL
script_stop: true # Stop execution on any error
script: |
echo "=== Starting deployment to staging server ==="
cd /opt/mypage-staging
# Registry configuration - insecure registry does not require authentication
echo "=== Registry Configuration ==="
echo "Registry: $REGISTRY_URL"
echo "Type: Insecure (no authentication required)"
echo " Skipping registry login"
echo ""
# Verify docker-compose.staging.yml exists (copied by previous step)
if [ ! -f docker-compose.staging.yml ]; then
echo "❌ docker-compose.staging.yml not found in /opt/mypage-staging"
echo "File should have been copied by CI/CD workflow"
exit 1
fi
echo "✅ Using docker-compose.staging.yml"
# Pull latest staging image from registry
echo "=== Pulling latest Docker image (staging) ==="
docker pull "$IMAGE_FULL"
if [ $? -ne 0 ]; then
echo "❌ Failed to pull image, aborting deployment"
exit 1
fi
# Deploy new container
# - Stops old container
# - Removes old container
# - Creates and starts new container with fresh image
echo "=== Deploying new staging container ==="
docker compose -f docker-compose.staging.yml up -d --force-recreate
if [ $? -ne 0 ]; then
echo "❌ Failed to deploy new container"
echo "Check logs above for errors"
exit 1
fi
# Check container status
echo "=== Container Status ==="
docker compose -f docker-compose.staging.yml ps
# Show recent logs for debugging
echo "=== Recent application logs ==="
docker compose -f docker-compose.staging.yml logs --tail=50
# Clean up old/unused images to save disk space
echo "=== Cleaning up old Docker images ==="
docker image prune -f
echo "✅ Staging deployment completed successfully ==="
- name: ❤️ Health check
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ vars.PRODUCTION_HOST }}
username: ${{ vars.PRODUCTION_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: 22
script: |
echo "=== Performing health check ==="
cd /opt/mypage-staging
max_attempts=15
attempt=1
# Wait for container to be healthy (respect start_period from health check)
echo "Waiting for application to start (40s start period)..."
sleep 40
# Retry health check up to 15 times
while [ $attempt -le $max_attempts ]; do
# Check if application responds at port 3031
if curl -f http://localhost:3031/ > /dev/null 2>&1; then
echo "✅ Health check passed!"
echo "Application is healthy and responding to requests"
exit 0
fi
echo "Attempt $attempt/$max_attempts: Health check failed, retrying in 5s..."
sleep 5
attempt=$((attempt + 1))
done
# Health check failed - gather diagnostic information
echo "❌ Health check failed after $max_attempts attempts"
echo ""
echo "=== Container Status ==="
docker compose -f docker-compose.staging.yml ps
echo ""
echo "=== Container Health ==="
docker inspect mypage-staging --format='{{.State.Health.Status}}' 2>/dev/null || echo "No health status"
echo ""
echo "=== Recent Application Logs ==="
docker compose -f docker-compose.staging.yml logs --tail=100
exit 1
- name: 📊 Deployment summary
if: always() # Run even if previous steps fail
run: |
echo "### 🚀 Deployment Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Environment**: Staging" >> $GITHUB_STEP_SUMMARY
echo "- **Image**: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:staging" >> $GITHUB_STEP_SUMMARY
echo "- **Commit**: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Workflow Run**: #${{ github.run_number }}" >> $GITHUB_STEP_SUMMARY
echo "- **Triggered By**: ${{ github.actor }}" >> $GITHUB_STEP_SUMMARY
echo "- **Status**: ${{ job.status }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Next Steps:**" >> $GITHUB_STEP_SUMMARY
echo "1. Verify application is accessible at http://192.168.1.54:3031" >> $GITHUB_STEP_SUMMARY
echo "2. Check application logs for any errors" >> $GITHUB_STEP_SUMMARY
echo "3. Test staging features before promoting to production" >> $GITHUB_STEP_SUMMARY

View File

@@ -13,29 +13,28 @@ draft: false
Daca te intrebi de ce aceata pagina? Pentru ca vreau sa jurnalizez lucrurile la care lucrez, sau gandurile pe care vreua sa le impartesesc. Daca te intrebi de ce aceata pagina? Pentru ca vreau sa jurnalizez lucrurile la care lucrez, sau gandurile pe care vreua sa le impartesesc.
## Why a blog? ## De ce blog?
You might be thinking, "Why create another tech blog? There are plenty out there." Dacă te gândești de ce să mai creezi inca un blog cand sunt atea pe net, pai ideea este ca este si ca un jurnal, unde postez lucruri si ma ajuta sa revin la ceea ce am investigat.
Well, yes, there are. But I believe that sharing some of my opinions and experiences will eventually act out as a journal:
1. **Personal touch**: Even though i've been working corporate all my career, this webpage won't contain that sugar coated language 😅. It's a place where you'll get to know me my thoughts, my mistakes, and my victories. I believe that this personal touch makes the content more engaging and relatable. 1. **Este personal**: Nu este un lucru formal, chiar daca am lucrat in corporate, unde toti se asteapta sa fii prietenos si zambaret mereu, aici o sa fie mai sincere opiniile.
2. **Beyond tech**: While I'll be writing about technology, I also want to explore other topics that interest me, such as mental health, productivity and so on.... I think a well-rounded approach can help create a more engaging and informative space. 2. **Mai mult decat tech**: O sa scriu despre tech dar, nu ăsta e focusul aici
3. **Self-hosting adventure**: As you might have guessed from the title, this blog is self-hosted. This was an exciting journey for me, and I'll be sharing my experiences, challenges, and learnings along the way. If you're interested in self-hosting or just want to understand what it's all about, you might find what worked for me or didn't. 3. **Cum fac selfhost**: Fac selfhost, la cateva servicii utile: git, webpage-ul acesta. O sa incerc sa povestesc si cum fac mentenanta sau ce probleme am intampinat pe parcursul acestor deploymenturi.
## Why self-host? ## De ce selfhost?
![Selfhosting rig](./whythispage/selfhostedrig.gif?w=400 "My self-hosting setup | A look at the hardware running this blog") ![Selfhosting rig](./whythispage/selfhostedrig.gif?w=400 "Acesta este pc-ul | Hardware-ul pe care ruleaza cest webpage")
Now, let's talk about why I chose to self-host this blog. In a nutshell, self-hosting gave me: Am inceput sa fac hosting acasa din cateva motive:
- **Full control**: By hosting my own website, I have complete control over my content and how it's displayed. No more compromises or limitations imposed by third-party platforms. - **Detin controlul**: Nu depind de cloud providers sau alte 3rd parties (inafara de VPS).
- **Owning my data**: It's just, that I can have control over my data without others snooping around. - **Nu exista scurgeri de informatii**: Sunt unele lucruri pe care nu as vrea sa le impartasesc cu marii provideri de servicii cloud.
- **It's fun**: Started looking into sysadmin/devops for a long time, after a burnout I stepped into selfhosting more convincingly. - **E destul de smecher**: Este destul de tare sa vezi cum datele ruleaza pe hardwareul de la tine din casa.
## What to expect ## Ce este aici de fapt
As I mentioned earlier, this blog will be a mix of tech tutorials, personal thoughts, and everything in between. Here's what you can look forward to: E un blog, o jurnalizare e ceea ce fac eu, ma ajuta sa tin evidenta cand explica lucruri.
- **Tech how-tos**: Step-by-step guides on various topics, from setting up your own development environment to configuring your server. - **Resurse tehnice**: Ghiduri pas cu pas despre diverse subiecte, de la configurarea propriului mediului de dezvoltare până la ajustarea serverului.
- **Self-hosting adventures**: My experiences, learnings, and tips on self-hosting, including challenges faced and solutions implemented. - **Experiențe personale cu selfhosting**: Ce realizat, cum am solutionat, provocari ...
- **Random musings**: Thoughts on productivity, mental health, and other interests of mine that might not be directly related to tech. - **Gânduri aleatorii**: Gânduri despre eficiența profesională, sănătatea mintală și alte interese personale care nu sunt direct legate de tehnologie.

135
docker-compose.staging.yml Normal file
View File

@@ -0,0 +1,135 @@
# Docker Compose Configuration for Staging Deployment
# This file is used by CI/CD to deploy the application on staging servers
#
# Key differences from production docker-compose.prod.yml:
# - Container name: mypage-staging (vs mypage-prod)
# - Port mapping: 3031:3030 (vs 3030:3030)
# - Network name: mypage-staging-network (vs mypage-network)
# - Image tag: staging (vs latest)
#
# Usage:
# 1. This file is automatically copied to server by CI/CD workflow
# 2. Server pulls image from registry: docker compose -f docker-compose.staging.yml pull
# 3. Server starts container: docker compose -f docker-compose.staging.yml up -d
#
# Manual deployment (if CI/CD is not available):
# ssh user@staging-server
# cd /opt/mypage-staging
# docker compose -f docker-compose.staging.yml pull
# docker compose -f docker-compose.staging.yml up -d --force-recreate
version: '3.8'
services:
mypage:
# Use pre-built image from private registry with staging tag
# This image is built and pushed by the CI/CD workflow
# Format: REGISTRY_URL/IMAGE_NAME:TAG
image: repository.workspace:5000/mypage:staging
container_name: mypage-staging
# Restart policy: always restart on failure or server reboot
# This ensures high availability in staging
restart: always
# Port mapping: host:container
# Staging runs on port 3031 to avoid conflicts with production (3030)
# The application will be accessible at http://SERVER_IP:3031
ports:
- "3031:3030"
# Staging environment variables
environment:
- NODE_ENV=production
- NEXT_TELEMETRY_DISABLED=1
- PORT=3030
- HOSTNAME=0.0.0.0
# Add any other staging-specific environment variables here
# Example:
# - DATABASE_URL=postgresql://user:pass@db:5432/mypage_staging
# - REDIS_URL=redis://redis:6379
# Persistent volumes for logs (optional)
# Uncomment if your application writes logs
volumes:
- ./data/logs:/app/logs
# Health check configuration
# Docker monitors the application and marks it unhealthy if checks fail
# If container is unhealthy, restart policy will trigger a restart
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3030/", "||", "exit", "1"]
interval: 30s # Check every 30 seconds
timeout: 10s # Wait up to 10 seconds for response
retries: 3 # Mark unhealthy after 3 consecutive failures
start_period: 40s # Grace period during container startup
# Resource limits for staging
# Prevents container from consuming all server resources
# deploy:
# resources:
# limits:
# cpus: '1.0' # Maximum 1 CPU core
# memory: 512M # Maximum 512MB RAM
# reservations:
# cpus: '0.25' # Reserve at least 0.25 CPU cores
# memory: 256M # Reserve at least 256MB RAM
# Network configuration
networks:
- mypage-staging-network
# Logging configuration
# Prevents logs from consuming all disk space
logging:
driver: "json-file"
options:
max-size: "10m" # Maximum 10MB per log file
max-file: "3" # Keep only 3 log files (30MB total)
# Network definition
networks:
mypage-staging-network:
driver: bridge
# ============================================
# Staging Deployment Commands
# ============================================
#
# Pull latest image from registry:
# docker compose -f docker-compose.staging.yml pull
#
# Start/update containers:
# docker compose -f docker-compose.staging.yml up -d --force-recreate
#
# View logs:
# docker compose -f docker-compose.staging.yml logs -f mypage
#
# Check health status:
# docker inspect mypage-staging | grep -A 10 Health
#
# Stop containers:
# docker compose -f docker-compose.staging.yml down
#
# Restart containers:
# docker compose -f docker-compose.staging.yml restart
#
# Remove old/unused images (cleanup):
# docker image prune -f
#
# ============================================
# Troubleshooting
# ============================================
#
# If container keeps restarting:
# 1. Check logs: docker compose -f docker-compose.staging.yml logs --tail=100
# 2. Check health: docker inspect mypage-staging | grep -A 10 Health
# 3. Verify port is not already in use: netstat -tulpn | grep 3031
# 4. Check resource usage: docker stats mypage-staging
#
# If health check fails:
# 1. Test manually: docker exec mypage-staging curl -f http://localhost:3030/
# 2. Check if Next.js server is running: docker exec mypage-staging ps aux
# 3. Verify environment variables: docker exec mypage-staging env
#

379
package-lock.json generated
View File

@@ -11,16 +11,16 @@
"dependencies": { "dependencies": {
"@tailwindcss/postcss": "^4.1.17", "@tailwindcss/postcss": "^4.1.17",
"@tailwindcss/typography": "^0.5.19", "@tailwindcss/typography": "^0.5.19",
"@types/node": "^24.10.0", "@types/node": "^24.10.1",
"@types/react": "^19.2.2", "@types/react": "^19.2.7",
"autoprefixer": "^10.4.21", "autoprefixer": "^10.4.22",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
"next": "^16.0.1", "next": "^16.0.7",
"next-intl": "^4.5.7", "next-intl": "^4.5.8",
"next-themes": "^0.4.6", "next-themes": "^0.4.6",
"postcss": "^8.5.6", "postcss": "^8.5.6",
"react": "^19.2.0", "react": "^19.2.1",
"react-dom": "^19.2.0", "react-dom": "^19.2.1",
"react-markdown": "^10.1.0", "react-markdown": "^10.1.0",
"rehype-raw": "^7.0.0", "rehype-raw": "^7.0.0",
"rehype-sanitize": "^6.0.0", "rehype-sanitize": "^6.0.0",
@@ -32,17 +32,17 @@
"unist-util-visit": "^5.0.0" "unist-util-visit": "^5.0.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/eslintrc": "^3.3.1", "@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^9.39.1", "@eslint/js": "^9.39.1",
"@next/bundle-analyzer": "^16.0.3", "@next/bundle-analyzer": "^16.0.7",
"@typescript-eslint/eslint-plugin": "^8.46.4", "@typescript-eslint/eslint-plugin": "^8.48.1",
"@typescript-eslint/parser": "^8.46.4", "@typescript-eslint/parser": "^8.48.1",
"eslint": "^9.39.1", "eslint": "^9.39.1",
"eslint-config-next": "^16.0.3", "eslint-config-next": "^16.0.7",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.4", "eslint-plugin-prettier": "^5.5.4",
"prettier": "^3.6.2", "prettier": "^3.7.4",
"typescript-eslint": "^8.46.4" "typescript-eslint": "^8.48.1"
} }
}, },
"node_modules/@alloc/quick-lru": { "node_modules/@alloc/quick-lru": {
@@ -453,9 +453,9 @@
} }
}, },
"node_modules/@eslint/eslintrc": { "node_modules/@eslint/eslintrc": {
"version": "3.3.1", "version": "3.3.3",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
"integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -465,7 +465,7 @@
"globals": "^14.0.0", "globals": "^14.0.0",
"ignore": "^5.2.0", "ignore": "^5.2.0",
"import-fresh": "^3.2.1", "import-fresh": "^3.2.1",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.1",
"minimatch": "^3.1.2", "minimatch": "^3.1.2",
"strip-json-comments": "^3.1.1" "strip-json-comments": "^3.1.1"
}, },
@@ -1202,9 +1202,9 @@
} }
}, },
"node_modules/@next/bundle-analyzer": { "node_modules/@next/bundle-analyzer": {
"version": "16.0.3", "version": "16.0.7",
"resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-16.0.3.tgz", "resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-16.0.7.tgz",
"integrity": "sha512-6Xo8f8/ZXtASfTPa6TH1aUn+xDg9Pkyl1YHVxu+89cVdLH7MnYjxv3rPOfEJ9BwCZCU2q4Flyw5MwltfD2pGbA==", "integrity": "sha512-Um2YA3TSQND+DpqlMDuPZsdjdpcgLzo1wF3zx4zcBCLecS7ucP7O9YFqvHhg000HXTgt++KIjZ9FUwyJSKk1Kw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1212,55 +1212,25 @@
} }
}, },
"node_modules/@next/env": { "node_modules/@next/env": {
"version": "16.0.1", "version": "16.0.7",
"resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.1.tgz", "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.7.tgz",
"integrity": "sha512-LFvlK0TG2L3fEOX77OC35KowL8D7DlFF45C0OvKMC4hy8c/md1RC4UMNDlUGJqfCoCS2VWrZ4dSE6OjaX5+8mw==", "integrity": "sha512-gpaNgUh5nftFKRkRQGnVi5dpcYSKGcZZkQffZ172OrG/XkrnS7UBTQ648YY+8ME92cC4IojpI2LqTC8sTDhAaw==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@next/eslint-plugin-next": { "node_modules/@next/eslint-plugin-next": {
"version": "16.0.3", "version": "16.0.7",
"resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.0.3.tgz", "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.0.7.tgz",
"integrity": "sha512-6sPWmZetzFWMsz7Dhuxsdmbu3fK+/AxKRtj7OB0/3OZAI2MHB/v2FeYh271LZ9abvnM1WIwWc/5umYjx0jo5sQ==", "integrity": "sha512-hFrTNZcMEG+k7qxVxZJq3F32Kms130FAhG8lvw2zkKBgAcNOJIxlljNiCjGygvBshvaGBdf88q2CqWtnqezDHA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"fast-glob": "3.3.1" "fast-glob": "3.3.1"
} }
}, },
"node_modules/@next/eslint-plugin-next/node_modules/fast-glob": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
"integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
"glob-parent": "^5.1.2",
"merge2": "^1.3.0",
"micromatch": "^4.0.4"
},
"engines": {
"node": ">=8.6.0"
}
},
"node_modules/@next/eslint-plugin-next/node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/@next/swc-darwin-arm64": { "node_modules/@next/swc-darwin-arm64": {
"version": "16.0.1", "version": "16.0.7",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.1.tgz", "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.7.tgz",
"integrity": "sha512-R0YxRp6/4W7yG1nKbfu41bp3d96a0EalonQXiMe+1H9GTHfKxGNCGFNWUho18avRBPsO8T3RmdWuzmfurlQPbg==", "integrity": "sha512-LlDtCYOEj/rfSnEn/Idi+j1QKHxY9BJFmxx7108A6D8K0SB+bNgfYQATPk/4LqOl4C0Wo3LACg2ie6s7xqMpJg==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1274,9 +1244,9 @@
} }
}, },
"node_modules/@next/swc-darwin-x64": { "node_modules/@next/swc-darwin-x64": {
"version": "16.0.1", "version": "16.0.7",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.1.tgz", "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.7.tgz",
"integrity": "sha512-kETZBocRux3xITiZtOtVoVvXyQLB7VBxN7L6EPqgI5paZiUlnsgYv4q8diTNYeHmF9EiehydOBo20lTttCbHAg==", "integrity": "sha512-rtZ7BhnVvO1ICf3QzfW9H3aPz7GhBrnSIMZyr4Qy6boXF0b5E3QLs+cvJmg3PsTCG2M1PBoC+DANUi4wCOKXpA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1290,9 +1260,9 @@
} }
}, },
"node_modules/@next/swc-linux-arm64-gnu": { "node_modules/@next/swc-linux-arm64-gnu": {
"version": "16.0.1", "version": "16.0.7",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.1.tgz", "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.7.tgz",
"integrity": "sha512-hWg3BtsxQuSKhfe0LunJoqxjO4NEpBmKkE+P2Sroos7yB//OOX3jD5ISP2wv8QdUwtRehMdwYz6VB50mY6hqAg==", "integrity": "sha512-mloD5WcPIeIeeZqAIP5c2kdaTa6StwP4/2EGy1mUw8HiexSHGK/jcM7lFuS3u3i2zn+xH9+wXJs6njO7VrAqww==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1306,9 +1276,9 @@
} }
}, },
"node_modules/@next/swc-linux-arm64-musl": { "node_modules/@next/swc-linux-arm64-musl": {
"version": "16.0.1", "version": "16.0.7",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.1.tgz", "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.7.tgz",
"integrity": "sha512-UPnOvYg+fjAhP3b1iQStcYPWeBFRLrugEyK/lDKGk7kLNua8t5/DvDbAEFotfV1YfcOY6bru76qN9qnjLoyHCQ==", "integrity": "sha512-+ksWNrZrthisXuo9gd1XnjHRowCbMtl/YgMpbRvFeDEqEBd523YHPWpBuDjomod88U8Xliw5DHhekBC3EOOd9g==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1322,9 +1292,9 @@
} }
}, },
"node_modules/@next/swc-linux-x64-gnu": { "node_modules/@next/swc-linux-x64-gnu": {
"version": "16.0.1", "version": "16.0.7",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.1.tgz", "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.7.tgz",
"integrity": "sha512-Et81SdWkcRqAJziIgFtsFyJizHoWne4fzJkvjd6V4wEkWTB4MX6J0uByUb0peiJQ4WeAt6GGmMszE5KrXK6WKg==", "integrity": "sha512-4WtJU5cRDxpEE44Ana2Xro1284hnyVpBb62lIpU5k85D8xXxatT+rXxBgPkc7C1XwkZMWpK5rXLXTh9PFipWsA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1338,9 +1308,9 @@
} }
}, },
"node_modules/@next/swc-linux-x64-musl": { "node_modules/@next/swc-linux-x64-musl": {
"version": "16.0.1", "version": "16.0.7",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.1.tgz", "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.7.tgz",
"integrity": "sha512-qBbgYEBRrC1egcG03FZaVfVxrJm8wBl7vr8UFKplnxNRprctdP26xEv9nJ07Ggq4y1adwa0nz2mz83CELY7N6Q==", "integrity": "sha512-HYlhqIP6kBPXalW2dbMTSuB4+8fe+j9juyxwfMwCe9kQPPeiyFn7NMjNfoFOfJ2eXkeQsoUGXg+O2SE3m4Qg2w==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1354,9 +1324,9 @@
} }
}, },
"node_modules/@next/swc-win32-arm64-msvc": { "node_modules/@next/swc-win32-arm64-msvc": {
"version": "16.0.1", "version": "16.0.7",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.1.tgz", "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.7.tgz",
"integrity": "sha512-cPuBjYP6I699/RdbHJonb3BiRNEDm5CKEBuJ6SD8k3oLam2fDRMKAvmrli4QMDgT2ixyRJ0+DTkiODbIQhRkeQ==", "integrity": "sha512-EviG+43iOoBRZg9deGauXExjRphhuYmIOJ12b9sAPy0eQ6iwcPxfED2asb/s2/yiLYOdm37kPaiZu8uXSYPs0Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1370,9 +1340,9 @@
} }
}, },
"node_modules/@next/swc-win32-x64-msvc": { "node_modules/@next/swc-win32-x64-msvc": {
"version": "16.0.1", "version": "16.0.7",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.1.tgz", "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.7.tgz",
"integrity": "sha512-XeEUJsE4JYtfrXe/LaJn3z1pD19fK0Q6Er8Qoufi+HqvdO4LEPyCxLUt4rxA+4RfYo6S9gMlmzCMU2F+AatFqQ==", "integrity": "sha512-gniPjy55zp5Eg0896qSrf3yB1dw4F/3s8VK1ephdsZZ129j2n6e1WqCbE2YgcKhW9hPB9TVZENugquWJD5x0ug==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1991,21 +1961,21 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "24.10.0", "version": "24.10.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz",
"integrity": "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==", "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"undici-types": "~7.16.0" "undici-types": "~7.16.0"
} }
}, },
"node_modules/@types/react": { "node_modules/@types/react": {
"version": "19.2.2", "version": "19.2.7",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz",
"integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"csstype": "^3.0.2" "csstype": "^3.2.2"
} }
}, },
"node_modules/@types/unist": { "node_modules/@types/unist": {
@@ -2015,17 +1985,17 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.46.4", "version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.4.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.48.1.tgz",
"integrity": "sha512-R48VhmTJqplNyDxCyqqVkFSZIx1qX6PzwqgcXn1olLrzxcSBDlOsbtcnQuQhNtnNiJ4Xe5gREI1foajYaYU2Vg==", "integrity": "sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.10.0", "@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.46.4", "@typescript-eslint/scope-manager": "8.48.1",
"@typescript-eslint/type-utils": "8.46.4", "@typescript-eslint/type-utils": "8.48.1",
"@typescript-eslint/utils": "8.46.4", "@typescript-eslint/utils": "8.48.1",
"@typescript-eslint/visitor-keys": "8.46.4", "@typescript-eslint/visitor-keys": "8.48.1",
"graphemer": "^1.4.0", "graphemer": "^1.4.0",
"ignore": "^7.0.0", "ignore": "^7.0.0",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
@@ -2039,22 +2009,22 @@
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
}, },
"peerDependencies": { "peerDependencies": {
"@typescript-eslint/parser": "^8.46.4", "@typescript-eslint/parser": "^8.48.1",
"eslint": "^8.57.0 || ^9.0.0", "eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0" "typescript": ">=4.8.4 <6.0.0"
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.46.4", "version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.4.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.48.1.tgz",
"integrity": "sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w==", "integrity": "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.46.4", "@typescript-eslint/scope-manager": "8.48.1",
"@typescript-eslint/types": "8.46.4", "@typescript-eslint/types": "8.48.1",
"@typescript-eslint/typescript-estree": "8.46.4", "@typescript-eslint/typescript-estree": "8.48.1",
"@typescript-eslint/visitor-keys": "8.46.4", "@typescript-eslint/visitor-keys": "8.48.1",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@@ -2070,14 +2040,14 @@
} }
}, },
"node_modules/@typescript-eslint/project-service": { "node_modules/@typescript-eslint/project-service": {
"version": "8.46.4", "version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.4.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.48.1.tgz",
"integrity": "sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==", "integrity": "sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.46.4", "@typescript-eslint/tsconfig-utils": "^8.48.1",
"@typescript-eslint/types": "^8.46.4", "@typescript-eslint/types": "^8.48.1",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@@ -2092,14 +2062,14 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.46.4", "version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.4.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.48.1.tgz",
"integrity": "sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==", "integrity": "sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.46.4", "@typescript-eslint/types": "8.48.1",
"@typescript-eslint/visitor-keys": "8.46.4" "@typescript-eslint/visitor-keys": "8.48.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2110,9 +2080,9 @@
} }
}, },
"node_modules/@typescript-eslint/tsconfig-utils": { "node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.46.4", "version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.4.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.48.1.tgz",
"integrity": "sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==", "integrity": "sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -2127,15 +2097,15 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.46.4", "version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.4.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.48.1.tgz",
"integrity": "sha512-V4QC8h3fdT5Wro6vANk6eojqfbv5bpwHuMsBcJUJkqs2z5XnYhJzyz9Y02eUmF9u3PgXEUiOt4w4KHR3P+z0PQ==", "integrity": "sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.46.4", "@typescript-eslint/types": "8.48.1",
"@typescript-eslint/typescript-estree": "8.46.4", "@typescript-eslint/typescript-estree": "8.48.1",
"@typescript-eslint/utils": "8.46.4", "@typescript-eslint/utils": "8.48.1",
"debug": "^4.3.4", "debug": "^4.3.4",
"ts-api-utils": "^2.1.0" "ts-api-utils": "^2.1.0"
}, },
@@ -2152,9 +2122,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.46.4", "version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.4.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.48.1.tgz",
"integrity": "sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==", "integrity": "sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -2166,21 +2136,20 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.46.4", "version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.4.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.48.1.tgz",
"integrity": "sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==", "integrity": "sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/project-service": "8.46.4", "@typescript-eslint/project-service": "8.48.1",
"@typescript-eslint/tsconfig-utils": "8.46.4", "@typescript-eslint/tsconfig-utils": "8.48.1",
"@typescript-eslint/types": "8.46.4", "@typescript-eslint/types": "8.48.1",
"@typescript-eslint/visitor-keys": "8.46.4", "@typescript-eslint/visitor-keys": "8.48.1",
"debug": "^4.3.4", "debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
"minimatch": "^9.0.4", "minimatch": "^9.0.4",
"semver": "^7.6.0", "semver": "^7.6.0",
"tinyglobby": "^0.2.15",
"ts-api-utils": "^2.1.0" "ts-api-utils": "^2.1.0"
}, },
"engines": { "engines": {
@@ -2195,16 +2164,16 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.46.4", "version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.4.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.48.1.tgz",
"integrity": "sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==", "integrity": "sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.7.0", "@eslint-community/eslint-utils": "^4.7.0",
"@typescript-eslint/scope-manager": "8.46.4", "@typescript-eslint/scope-manager": "8.48.1",
"@typescript-eslint/types": "8.46.4", "@typescript-eslint/types": "8.48.1",
"@typescript-eslint/typescript-estree": "8.46.4" "@typescript-eslint/typescript-estree": "8.48.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2219,13 +2188,13 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.46.4", "version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.4.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.48.1.tgz",
"integrity": "sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==", "integrity": "sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.46.4", "@typescript-eslint/types": "8.48.1",
"eslint-visitor-keys": "^4.2.1" "eslint-visitor-keys": "^4.2.1"
}, },
"engines": { "engines": {
@@ -2790,9 +2759,9 @@
} }
}, },
"node_modules/autoprefixer": { "node_modules/autoprefixer": {
"version": "10.4.21", "version": "10.4.22",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz",
"integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==",
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@@ -2809,9 +2778,9 @@
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"browserslist": "^4.24.4", "browserslist": "^4.27.0",
"caniuse-lite": "^1.0.30001702", "caniuse-lite": "^1.0.30001754",
"fraction.js": "^4.3.7", "fraction.js": "^5.3.4",
"normalize-range": "^0.1.2", "normalize-range": "^0.1.2",
"picocolors": "^1.1.1", "picocolors": "^1.1.1",
"postcss-value-parser": "^4.2.0" "postcss-value-parser": "^4.2.0"
@@ -3179,9 +3148,9 @@
} }
}, },
"node_modules/csstype": { "node_modules/csstype": {
"version": "3.1.3", "version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/damerau-levenshtein": { "node_modules/damerau-levenshtein": {
@@ -3694,13 +3663,13 @@
} }
}, },
"node_modules/eslint-config-next": { "node_modules/eslint-config-next": {
"version": "16.0.3", "version": "16.0.7",
"resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.0.3.tgz", "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.0.7.tgz",
"integrity": "sha512-5F6qDjcZldf0Y0ZbqvWvap9xzYUxyDf7/of37aeyhvkrQokj/4bT1JYWZdlWUr283aeVa+s52mPq9ogmGg+5dw==", "integrity": "sha512-WubFGLFHfk2KivkdRGfx6cGSFhaQqhERRfyO8BRx+qiGPGp7WLKcPvYC4mdx1z3VhVRcrfFzczjjTrbJZOpnEQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@next/eslint-plugin-next": "16.0.3", "@next/eslint-plugin-next": "16.0.7",
"eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-node": "^0.3.6",
"eslint-import-resolver-typescript": "^3.5.2", "eslint-import-resolver-typescript": "^3.5.2",
"eslint-plugin-import": "^2.32.0", "eslint-plugin-import": "^2.32.0",
@@ -4325,9 +4294,9 @@
"license": "Apache-2.0" "license": "Apache-2.0"
}, },
"node_modules/fast-glob": { "node_modules/fast-glob": {
"version": "3.3.3", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -4335,7 +4304,7 @@
"@nodelib/fs.walk": "^1.2.3", "@nodelib/fs.walk": "^1.2.3",
"glob-parent": "^5.1.2", "glob-parent": "^5.1.2",
"merge2": "^1.3.0", "merge2": "^1.3.0",
"micromatch": "^4.0.8" "micromatch": "^4.0.4"
}, },
"engines": { "engines": {
"node": ">=8.6.0" "node": ">=8.6.0"
@@ -4459,15 +4428,15 @@
} }
}, },
"node_modules/fraction.js": { "node_modules/fraction.js": {
"version": "4.3.7", "version": "5.3.4",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
"integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": "*" "node": "*"
}, },
"funding": { "funding": {
"type": "patreon", "type": "github",
"url": "https://github.com/sponsors/rawify" "url": "https://github.com/sponsors/rawify"
} }
}, },
@@ -7007,12 +6976,12 @@
} }
}, },
"node_modules/next": { "node_modules/next": {
"version": "16.0.1", "version": "16.0.7",
"resolved": "https://registry.npmjs.org/next/-/next-16.0.1.tgz", "resolved": "https://registry.npmjs.org/next/-/next-16.0.7.tgz",
"integrity": "sha512-e9RLSssZwd35p7/vOa+hoDFggUZIUbZhIUSLZuETCwrCVvxOs87NamoUzT+vbcNAL8Ld9GobBnWOA6SbV/arOw==", "integrity": "sha512-3mBRJyPxT4LOxAJI6IsXeFtKfiJUbjCLgvXO02fV8Wy/lIhPvP94Fe7dGhUgHXcQy4sSuYwQNcOLhIfOm0rL0A==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@next/env": "16.0.1", "@next/env": "16.0.7",
"@swc/helpers": "0.5.15", "@swc/helpers": "0.5.15",
"caniuse-lite": "^1.0.30001579", "caniuse-lite": "^1.0.30001579",
"postcss": "8.4.31", "postcss": "8.4.31",
@@ -7025,14 +6994,14 @@
"node": ">=20.9.0" "node": ">=20.9.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@next/swc-darwin-arm64": "16.0.1", "@next/swc-darwin-arm64": "16.0.7",
"@next/swc-darwin-x64": "16.0.1", "@next/swc-darwin-x64": "16.0.7",
"@next/swc-linux-arm64-gnu": "16.0.1", "@next/swc-linux-arm64-gnu": "16.0.7",
"@next/swc-linux-arm64-musl": "16.0.1", "@next/swc-linux-arm64-musl": "16.0.7",
"@next/swc-linux-x64-gnu": "16.0.1", "@next/swc-linux-x64-gnu": "16.0.7",
"@next/swc-linux-x64-musl": "16.0.1", "@next/swc-linux-x64-musl": "16.0.7",
"@next/swc-win32-arm64-msvc": "16.0.1", "@next/swc-win32-arm64-msvc": "16.0.7",
"@next/swc-win32-x64-msvc": "16.0.1", "@next/swc-win32-x64-msvc": "16.0.7",
"sharp": "^0.34.4" "sharp": "^0.34.4"
}, },
"peerDependencies": { "peerDependencies": {
@@ -7059,9 +7028,9 @@
} }
}, },
"node_modules/next-intl": { "node_modules/next-intl": {
"version": "4.5.7", "version": "4.5.8",
"resolved": "https://registry.npmjs.org/next-intl/-/next-intl-4.5.7.tgz", "resolved": "https://registry.npmjs.org/next-intl/-/next-intl-4.5.8.tgz",
"integrity": "sha512-7iT9rBEFZvsJI5uLoOLgI1kAieg1k7zCwbuby6ylKRbpvt08I1vkZ5FJnIBey1M+r1jam/wANlnqRYeJagjL2Q==", "integrity": "sha512-BdN6494nvt09WtmW5gbWdwRhDDHC/Sg7tBMhN7xfYds3vcRCngSDXat81gmJkblw9jYOv8zXzzFJyu5VYXnJzg==",
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -7073,9 +7042,9 @@
"@formatjs/intl-localematcher": "^0.5.4", "@formatjs/intl-localematcher": "^0.5.4",
"@swc/core": "^1.15.2", "@swc/core": "^1.15.2",
"negotiator": "^1.0.0", "negotiator": "^1.0.0",
"next-intl-swc-plugin-extractor": "^4.5.7", "next-intl-swc-plugin-extractor": "^4.5.8",
"po-parser": "^1.0.2", "po-parser": "^1.0.2",
"use-intl": "^4.5.7" "use-intl": "^4.5.8"
}, },
"peerDependencies": { "peerDependencies": {
"next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", "next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
@@ -7089,9 +7058,9 @@
} }
}, },
"node_modules/next-intl-swc-plugin-extractor": { "node_modules/next-intl-swc-plugin-extractor": {
"version": "4.5.7", "version": "4.5.8",
"resolved": "https://registry.npmjs.org/next-intl-swc-plugin-extractor/-/next-intl-swc-plugin-extractor-4.5.7.tgz", "resolved": "https://registry.npmjs.org/next-intl-swc-plugin-extractor/-/next-intl-swc-plugin-extractor-4.5.8.tgz",
"integrity": "sha512-cSHtDpEoSHuEC4CzUDmAAfB0H3fqSephpJNd/GtS9LvUoZM78wJQwkEaqN9yTxXEvJ8uQG60nnOeSl2LQU9qdQ==", "integrity": "sha512-hscCKUv+5GQ0CCNbvqZ8gaxnAGToCgDTbL++jgCq8SCk/ljtZDEeQZcMk46Nm6Ynn49Q/JKF4Npo/Sq1mpbusA==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/next-intl/node_modules/@swc/core": { "node_modules/next-intl/node_modules/@swc/core": {
@@ -7567,9 +7536,9 @@
} }
}, },
"node_modules/prettier": { "node_modules/prettier": {
"version": "3.6.2", "version": "3.7.4",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz",
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"bin": { "bin": {
@@ -7649,24 +7618,24 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/react": { "node_modules/react": {
"version": "19.2.0", "version": "19.2.1",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz",
"integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/react-dom": { "node_modules/react-dom": {
"version": "19.2.0", "version": "19.2.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.1.tgz",
"integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "integrity": "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"scheduler": "^0.27.0" "scheduler": "^0.27.0"
}, },
"peerDependencies": { "peerDependencies": {
"react": "^19.2.0" "react": "^19.2.1"
} }
}, },
"node_modules/react-is": { "node_modules/react-is": {
@@ -8775,16 +8744,16 @@
} }
}, },
"node_modules/typescript-eslint": { "node_modules/typescript-eslint": {
"version": "8.46.4", "version": "8.48.1",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.46.4.tgz", "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.48.1.tgz",
"integrity": "sha512-KALyxkpYV5Ix7UhvjTwJXZv76VWsHG+NjNlt/z+a17SOQSiOcBdUXdbJdyXi7RPxrBFECtFOiPwUJQusJuCqrg==", "integrity": "sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/eslint-plugin": "8.46.4", "@typescript-eslint/eslint-plugin": "8.48.1",
"@typescript-eslint/parser": "8.46.4", "@typescript-eslint/parser": "8.48.1",
"@typescript-eslint/typescript-estree": "8.46.4", "@typescript-eslint/typescript-estree": "8.48.1",
"@typescript-eslint/utils": "8.46.4" "@typescript-eslint/utils": "8.48.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -8986,9 +8955,9 @@
} }
}, },
"node_modules/use-intl": { "node_modules/use-intl": {
"version": "4.5.7", "version": "4.5.8",
"resolved": "https://registry.npmjs.org/use-intl/-/use-intl-4.5.7.tgz", "resolved": "https://registry.npmjs.org/use-intl/-/use-intl-4.5.8.tgz",
"integrity": "sha512-WBVD1fxV9td5osQFK0TRQhz217zHERhxBuA3EmZuH7wCINJPXbYPs+0FH2oMpy6p6BBwuHCJK2ER8hKwxf0LQA==", "integrity": "sha512-rWPV2Sirw55BQbA/7ndUBtsikh8WXwBrUkZJ1mD35+emj/ogPPqgCZdv1DdrEFK42AjF1g5w8d3x8govhqPH6Q==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@formatjs/fast-memoize": "^2.2.0", "@formatjs/fast-memoize": "^2.2.0",

View File

@@ -30,16 +30,16 @@
"dependencies": { "dependencies": {
"@tailwindcss/postcss": "^4.1.17", "@tailwindcss/postcss": "^4.1.17",
"@tailwindcss/typography": "^0.5.19", "@tailwindcss/typography": "^0.5.19",
"@types/node": "^24.10.0", "@types/node": "^24.10.1",
"@types/react": "^19.2.2", "@types/react": "^19.2.7",
"autoprefixer": "^10.4.21", "autoprefixer": "^10.4.22",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
"next": "^16.0.1", "next": "^16.0.7",
"next-intl": "^4.5.7", "next-intl": "^4.5.8",
"next-themes": "^0.4.6", "next-themes": "^0.4.6",
"postcss": "^8.5.6", "postcss": "^8.5.6",
"react": "^19.2.0", "react": "^19.2.1",
"react-dom": "^19.2.0", "react-dom": "^19.2.1",
"react-markdown": "^10.1.0", "react-markdown": "^10.1.0",
"rehype-raw": "^7.0.0", "rehype-raw": "^7.0.0",
"rehype-sanitize": "^6.0.0", "rehype-sanitize": "^6.0.0",
@@ -51,16 +51,16 @@
"unist-util-visit": "^5.0.0" "unist-util-visit": "^5.0.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/eslintrc": "^3.3.1", "@eslint/eslintrc": "^3.3.3",
"@eslint/js": "^9.39.1", "@eslint/js": "^9.39.1",
"@next/bundle-analyzer": "^16.0.3", "@next/bundle-analyzer": "^16.0.7",
"@typescript-eslint/eslint-plugin": "^8.46.4", "@typescript-eslint/eslint-plugin": "^8.48.1",
"@typescript-eslint/parser": "^8.46.4", "@typescript-eslint/parser": "^8.48.1",
"eslint": "^9.39.1", "eslint": "^9.39.1",
"eslint-config-next": "^16.0.3", "eslint-config-next": "^16.0.7",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.4", "eslint-plugin-prettier": "^5.5.4",
"prettier": "^3.6.2", "prettier": "^3.7.4",
"typescript-eslint": "^8.46.4" "typescript-eslint": "^8.48.1"
} }
} }

View File

@@ -1,20 +0,0 @@
---
title: 'Technical Article'
description: 'A technical article to test internal links'
date: '2025-01-10'
author: 'John Doe'
category: 'Tech'
tags: ['tech', 'test']
---
# Technical Article
This is a test article for internal blog post linking.
Imagine cooler:
![Cooler image:](articol-tehnic.md)
## Content
You are reading the technical article that was linked from the example post.