diff --git a/docs/FRONTEND_CONVENTIONS.md b/docs/FRONTEND_CONVENTIONS.md new file mode 100644 index 0000000..8ccc3a2 --- /dev/null +++ b/docs/FRONTEND_CONVENTIONS.md @@ -0,0 +1,108 @@ +# Frontend Conventions + +This document defines conventions for all frontend repos consuming Payload CMS via `@c2s/payload-contracts`. + +## Setup + +### Install Contracts Package (Git dependency) + +```json +{ + "dependencies": { + "@c2s/payload-contracts": "github:complexcaresolutions/payload-contracts" + } +} +``` + +```bash +pnpm install +``` + +### Environment Variables + +Every frontend needs these in `.env.local`: + +```env +NEXT_PUBLIC_PAYLOAD_URL=https://cms.c2sgmbh.de +NEXT_PUBLIC_TENANT_ID= +NEXT_PUBLIC_TENANT_SLUG= +NEXT_PUBLIC_SITE_URL=https:// +NODE_ENV=production +``` + +### API Client Initialization + +```typescript +// src/lib/cms.ts +import { createPayloadClient } from '@c2s/payload-contracts/api-client' + +export const cms = createPayloadClient({ + baseUrl: process.env.NEXT_PUBLIC_PAYLOAD_URL!, + tenantId: process.env.NEXT_PUBLIC_TENANT_ID!, +}) +``` + +### Block Renderer Setup + +```typescript +// src/components/blocks/index.tsx +import { createBlockRenderer } from '@c2s/payload-contracts/blocks' +import { HeroBlock } from './HeroBlock' +import { TextBlock } from './TextBlock' +// ... import site-specific block components + +export const BlockRenderer = createBlockRenderer({ + 'hero-block': HeroBlock, + 'text-block': TextBlock, + // Register only blocks this site uses +}) +``` + +## Git Workflow + +| Branch | Purpose | Deployment | +|--------|---------|------------| +| `develop` | Active development | Staging (sv-frontend) | +| `main` | Production-ready | Plesk auto-deploy | + +### Commit Conventions + +``` +feat: add hero block component +fix: correct image aspect ratio in card grid +refactor: extract shared section header component +``` + +## TypeScript Standards + +- Strict mode enabled +- Import types from `@c2s/payload-contracts`, never define CMS types locally +- Use `BlockByType<'hero-block'>` for block component props +- All API calls through the shared client, never raw `fetch` to CMS + +## Block Component Pattern + +```typescript +// src/components/blocks/HeroBlock.tsx +import type { BlockByType } from '@c2s/payload-contracts/types' +import { getImageUrl } from '@c2s/payload-contracts/types' + +type Props = Omit, 'blockType'> + +export function HeroBlock({ title, subtitle, image, ctaButtons }: Props) { + const imageUrl = getImageUrl(image, 'xlarge') + // ... render +} +``` + +## Updating Contracts + +When a work order arrives: + +1. `pnpm update @c2s/payload-contracts` (or `pnpm install` for Git deps) +2. Check `node_modules/@c2s/payload-contracts/work-orders/` for instructions +3. Implement changes +4. `pnpm build` to verify types +5. Commit and push to `develop` +6. Test on staging +7. Merge to `main` for production deploy diff --git a/templates/github-workflows/ci.yml b/templates/github-workflows/ci.yml new file mode 100644 index 0000000..c7632d1 --- /dev/null +++ b/templates/github-workflows/ci.yml @@ -0,0 +1,35 @@ +# CI Workflow Template for Frontend Repos +# Copy to: .github/workflows/ci.yml +name: CI + +on: + push: + branches: [develop, main] + pull_request: + branches: [develop] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: 10 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + + - run: pnpm install --frozen-lockfile + + - run: pnpm lint + + - run: pnpm build + env: + NEXT_PUBLIC_PAYLOAD_URL: https://cms.c2sgmbh.de + NEXT_PUBLIC_TENANT_ID: ${{ vars.TENANT_ID }} + NEXT_PUBLIC_TENANT_SLUG: ${{ vars.TENANT_SLUG }} + NEXT_PUBLIC_SITE_URL: ${{ vars.SITE_URL }} diff --git a/templates/github-workflows/deploy-staging.yml b/templates/github-workflows/deploy-staging.yml new file mode 100644 index 0000000..8fd58f9 --- /dev/null +++ b/templates/github-workflows/deploy-staging.yml @@ -0,0 +1,32 @@ +# Staging Deploy Template for Frontend Repos +# Copy to: .github/workflows/deploy-staging.yml +# Requires secret: FRONTEND_SSH_KEY (SSH key for sv-frontend) +name: Deploy Staging + +on: + push: + branches: [develop] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Deploy to sv-frontend + uses: appleboy/ssh-action@v1 + with: + host: 10.10.181.104 + username: frontend + key: ${{ secrets.FRONTEND_SSH_KEY }} + script: | + REPO_NAME="${{ github.event.repository.name }}" + cd ~/frontend.${REPO_NAME#frontend.} + + git fetch origin develop + git reset --hard origin/develop + + export PATH="/home/frontend/.local/share/pnpm:$PATH" + pnpm install --frozen-lockfile + pnpm build + + # Restart if using PM2 + pm2 restart "frontend-${REPO_NAME#frontend.}" --silent 2>/dev/null || true diff --git a/templates/plesk-post-deploy.sh b/templates/plesk-post-deploy.sh new file mode 100644 index 0000000..6eb2bd6 --- /dev/null +++ b/templates/plesk-post-deploy.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Plesk Post-Deploy Script +# Configure in: Plesk → Domain → Git → Post-deploy actions +# +# This runs after Plesk pulls the latest code from the main branch. + +set -e + +export NODE_ENV=production +export PATH=/opt/plesk/node/22/bin:$PATH + +echo "[deploy] Installing dependencies..." +pnpm install --frozen-lockfile 2>/dev/null || npm ci + +echo "[deploy] Building..." +pnpm build 2>/dev/null || npm run build + +echo "[deploy] Restarting application..." +touch tmp/restart.txt + +echo "[deploy] Done!"