diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3ae5a88..bb2304d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,37 +1,49 @@ -name: Next.js CI - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -permissions: - contents: read - -jobs: - build: - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [20.x] - - steps: - - name: Checkout repository - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Setup Node.js - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 - with: - node-version: ${{ matrix.node-version }} - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Run Lint - run: npm run lint - - - name: Build project - run: npm run build \ No newline at end of file +name: Next.js CI + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [22.x] + + steps: + - name: Checkout repository + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + persist-credentials: false + + - name: Setup Node.js + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: ${{ matrix.node-version }} + cache: ${{ hashFiles('package-lock.json') != '' && 'npm' || '' }} + cache-dependency-path: ${{ hashFiles('package-lock.json') != '' && 'package-lock.json' || '' }} + + - name: Install dependencies + run: | + if [ -f package-lock.json ]; then + npm ci + else + npm install + fi + + - name: Run Lint + run: npm run lint + + - name: Build project + run: npm run build \ No newline at end of file diff --git a/.github/workflows/nextjs.yml b/.github/workflows/nextjs.yml index ed74736..34703c8 100644 --- a/.github/workflows/nextjs.yml +++ b/.github/workflows/nextjs.yml @@ -1,36 +1,28 @@ -# Sample workflow for building and deploying a Next.js site to GitHub Pages -# -# To get started with Next.js see: https://nextjs.org/docs/getting-started -# name: Deploy Next.js site to Pages on: - # Runs on pushes targeting the default branch push: branches: ["main"] - - # Allows you to run this workflow manually from the Actions tab + pull_request: + branches: ["main"] workflow_dispatch: -# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: contents: read - pages: write - id-token: write -# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. -# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. concurrency: - group: "pages" + group: ${{ github.event_name == 'pull_request' && format('pages-pr-{0}', github.event.pull_request.number) || 'pages' }} cancel-in-progress: false jobs: - # Build job build: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + persist-credentials: false + - name: Detect package manager id: detect-package-manager run: | @@ -38,50 +30,60 @@ jobs: echo "manager=yarn" >> $GITHUB_OUTPUT echo "command=install" >> $GITHUB_OUTPUT echo "runner=yarn" >> $GITHUB_OUTPUT + echo "lockfile=yarn.lock" >> $GITHUB_OUTPUT exit 0 - elif [ -f "${{ github.workspace }}/package.json" ]; then + elif [ -f "${{ github.workspace }}/package-lock.json" ]; then echo "manager=npm" >> $GITHUB_OUTPUT echo "command=ci" >> $GITHUB_OUTPUT echo "runner=npx --no-install" >> $GITHUB_OUTPUT + echo "lockfile=package-lock.json" >> $GITHUB_OUTPUT + exit 0 + elif [ -f "${{ github.workspace }}/package.json" ]; then + echo "manager=npm" >> $GITHUB_OUTPUT + echo "command=install" >> $GITHUB_OUTPUT + echo "runner=npx --no-install" >> $GITHUB_OUTPUT + echo "lockfile=" >> $GITHUB_OUTPUT exit 0 else echo "Unable to determine package manager" exit 1 fi + - name: Setup Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: - node-version: "20" - cache: ${{ steps.detect-package-manager.outputs.manager }} + node-version: "22" + cache: ${{ steps.detect-package-manager.outputs.lockfile != '' && steps.detect-package-manager.outputs.manager || '' }} + cache-dependency-path: ${{ steps.detect-package-manager.outputs.lockfile }} + - name: Setup Pages - uses: actions/configure-pages@v5 - with: - # Automatically inject basePath in your Next.js configuration file and disable - # server side image optimization (https://nextjs.org/docs/api-reference/next/image#unoptimized). - # - # You may remove this line if you want to manage the configuration yourself. - static_site_generator: next + uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v5 + - name: Restore cache - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: | .next/cache - # Generate a new cache whenever packages or source files change. key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }} - # If source files changed but packages didn't, rebuild from a prior cache. restore-keys: | ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}- + - name: Install dependencies run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }} + - name: Build with Next.js run: ${{ steps.detect-package-manager.outputs.runner }} next build + - name: Upload artifact - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3 with: path: ./out - # Deployment job deploy: + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + permissions: + pages: write + id-token: write environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} @@ -90,4 +92,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5 diff --git a/AGENTS.md b/AGENTS.md index 24be58b..01ffc38 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -35,6 +35,6 @@ TODO: Project-specific context and directives for AI agents. ## 📦 Project Boundaries -- **Config alias map:** Webpack & Turbopack alias resolvers are manually defined in [`next.config.ts`](next.config.ts) mapping `"next-intl/config"` to our local request setup. Do not import the native `@swc/core` compiler plugin wrapper `createNextIntlPlugin` directly to avoid security policy native module blocks. +- **Config Alias Map:** Turbopack and Webpack alias resolvers map `"next-intl/config"` to our local request setup inside [`next.config.ts`](next.config.ts) using `createNextIntlPlugin("./src/i18n/request.ts")`. - **Branding Assets:** The official branding logo, favicon, and style specifications reside inside [`public/brand/`](public/brand/). diff --git a/next.config.ts b/next.config.ts index ef8ec19..929c1f4 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,17 +1,18 @@ import type { NextConfig } from "next"; +import createNextIntlPlugin from "next-intl/plugin"; import path from "path"; +const withNextIntl = createNextIntlPlugin("./src/i18n/request.ts"); + const nextConfig: NextConfig = { output: "export", images: { unoptimized: true, }, turbopack: { - root: path.resolve(process.cwd()), - resolveAlias: { - "next-intl/config": "./src/i18n/request.ts", - }, + root: path.resolve(__dirname), }, }; -export default nextConfig; +export default withNextIntl(nextConfig); + diff --git a/src/app/[locale]/layout.tsx b/src/app/[locale]/layout.tsx index 59d899e..3d7ca06 100644 --- a/src/app/[locale]/layout.tsx +++ b/src/app/[locale]/layout.tsx @@ -3,8 +3,9 @@ import { Inter, Noto_Sans_Devanagari } from "next/font/google"; import { routing } from "@/i18n/routing"; import { generateLocaleMetadata } from "@/i18n/metadata"; import { notFound } from "next/navigation"; -import { getMessages, setRequestLocale } from "next-intl/server"; +import { setRequestLocale } from "next-intl/server"; import { NextIntlClientProvider } from "next-intl"; +import { messagesMap, defaultMessages } from "@/i18n/messages"; import { ThemeProvider } from "@/components/providers/theme-provider"; import { LenisProvider } from "@/components/providers/lenis-provider"; import "./globals.css"; @@ -12,11 +13,13 @@ import "./globals.css"; const inter = Inter({ variable: "--font-inter", subsets: ["latin"], + display: "swap", }); const devanagari = Noto_Sans_Devanagari({ variable: "--font-devanagari", subsets: ["devanagari"], + display: "swap", }); export const dynamicParams = false; @@ -34,6 +37,7 @@ export async function generateMetadata({ if (!routing.locales.includes(locale as (typeof routing.locales)[number])) { notFound(); } + setRequestLocale(locale); return generateLocaleMetadata(locale, "Home"); } @@ -55,8 +59,8 @@ export default async function RootLayout({ // Enable static rendering setRequestLocale(locale); - // Provide messages to Client Components - const messages = await getMessages({ locale }); + // Provide messages to Client Components directly via messagesMap + const messages = messagesMap[locale] || defaultMessages; return ( -
-