Skip to content
Open

Prod #101

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
266686c
feat: make homepage feature cards clickable
marcelo-m7 Aug 14, 2025
214eaf1
Merge pull request #3 from Monynha-Softwares/codex/fix-syntax-error-i…
marcelo-m7 Aug 14, 2025
66f25ca
feat: update institutional messaging and translations
marcelo-m7 Aug 14, 2025
7b0aef2
Merge pull request #4 from Monynha-Softwares/codex/update-institution…
marcelo-m7 Aug 14, 2025
287c124
style: center team section cards
marcelo-m7 Aug 14, 2025
e0396eb
feat: redesign footer with ecosystem links
marcelo-m7 Aug 14, 2025
a42b972
Merge pull request #5 from Monynha-Softwares/codex/centralize-layout-…
marcelo-m7 Aug 14, 2025
9c1be3c
Merge pull request #6 from Monynha-Softwares/codex/update-footer-comp…
marcelo-m7 Aug 14, 2025
cf1986f
Revert "feat: redesign footer with ecosystem links"
marcelo-m7 Aug 14, 2025
752863b
Merge pull request #7 from Monynha-Softwares/revert-6-codex/update-fo…
marcelo-m7 Aug 14, 2025
ebd12f4
feat: expand footer with ecosystem and contact
marcelo-m7 Aug 14, 2025
7f6a10a
Merge pull request #8 from Monynha-Softwares/codex/update-site-footer…
marcelo-m7 Aug 14, 2025
dbcf0ad
Merge pull request #10 from Monynha-Softwares/main
marcelo-m7 Aug 14, 2025
2ad2b66
Sync branchs (#15)
marcelo-m7 Sep 15, 2025
2f89014
Sync with dev (#29)
marcelo-m7 Sep 16, 2025
eb929a4
Implementar listagem e comentarios no blog cqka45 (#66)
marcelo-m7 Sep 17, 2025
2f99c9d
Refactor blog post IDs to Supabase UUIDs (#100)
marcelo-m7 Oct 17, 2025
7c23360
chore: align environment docs and verify migrations (#102)
marcelo-m7 Oct 18, 2025
872ea4c
Add Payload collections for Supabase-backed content (#105)
marcelo-m7 Oct 18, 2025
ee06785
Feat/cms (#117)
marcelo-m7 Oct 18, 2025
9ce2d6d
Fix UI and UX errors in main branch (#119)
Copilot Oct 27, 2025
7639247
Refactor: Extract duplicated CMS collection patterns into shared util…
Copilot Nov 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Prevent host dependencies and build artifacts from being copied into the image
node_modules
cms/node_modules
.dist
cms/.payload
cms/dist
cms/build
.vercel
*.log
npm-debug.log*
yarn-error.log*
.DS_Store
.git
5 changes: 4 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Frontend application
VITE_SUPABASE_URL=
VITE_SUPABASE_ANON_KEY=
SITE_URL=

# Shared Supabase access
SUPABASE_PROJECT_ID=
SUPABASE_SERVICE_ROLE_KEY=
SITE_URL=
56 changes: 56 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ jobs:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm --prefix cms ci
- run: npm run cleanup-lovable
- run: npm run format
- run: npm run lint
- run: npm run cms:lint
- run: npm test

build:
Expand All @@ -36,18 +38,72 @@ jobs:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm --prefix cms ci
- run: npm run cleanup-lovable
- run: npm run format
- run: npm run lint
- run: npm run cms:lint
- run: npm run sitemap
- run: npm run build
- run: npm run cms:build
- name: Upload build artifact
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v4
with:
name: build
path: dist

deploy_spa:
needs: [build]
if: github.ref == 'refs/heads/prod' && github.event_name == 'push'
runs-on: ubuntu-latest
environment:
name: spa-production
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm run build
- name: Archive SPA bundle
run: tar -czf spa-dist.tar.gz -C dist .
- name: Upload SPA release bundle
uses: actions/upload-artifact@v4
with:
name: spa-dist
path: spa-dist.tar.gz
- name: Placeholder deploy command
run: |
echo "Deploying SPA to production environment"

deploy_cms:
needs: [build]
if: github.ref == 'refs/heads/prod' && github.event_name == 'push'
runs-on: ubuntu-latest
environment:
name: cms-production
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm --prefix cms ci
- run: npm --prefix cms run build
- name: Archive CMS build output
run: tar -czf cms-dist.tar.gz -C cms/dist .
- name: Upload CMS release bundle
uses: actions/upload-artifact@v4
with:
name: cms-dist
path: cms-dist.tar.gz
- name: Placeholder deploy command
run: |
echo "Deploying Payload CMS to production environment"

# deploy-preview:
# needs: build
# if: github.event_name == 'pull_request'
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@ dist-ssr
*.sw?

supabase/.temp

.env
cms/.env

94 changes: 94 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Agent Notes

## Supabase blog post UUID migration
- Migration `20250731120000-create-blog-posts-table.sql` now enforces
`public.blog_posts.id` as a `uuid` with `gen_random_uuid()` and backfills any
legacy `text` identifiers (including cascading updates for `public.comments`).
- Payload CMS posts now store their Supabase UUID in the hidden `supabaseId`
field; the after-change hook syncs both directions using Supabase-generated
IDs.
- TypeScript definitions under `src/integrations/supabase/types.ts` expose a
shared `UUID` alias so frontend code treats `blog_posts` and `comments`
identifiers as UUID values.

## Data cleanup summary
- Legacy `text` IDs are renamed to `legacy_id` during the migration, random UUIDs
are generated per row, and comment foreign keys are rewritten before the
`legacy_id` column is dropped.

## Next steps
- Run the updated migration in every Supabase environment and verify that the
comment foreign-key backfill succeeds (no rows should retain `legacy_id`).
- After deploying, execute an end-to-end blog comment publish flow (CMS ➜
Supabase ➜ `/blog/[slug]`) and confirm UUID identifiers propagate correctly.
- Update any downstream services that previously referenced the numeric/text blog
IDs so they read the new UUID format instead.

## CMS collection sync (2025-02-15)
- Payload CMS now exposes collections for: `solutions`, `repositories`,
`teamMembers`, `homepageFeatures`, `siteSettings`, `newsletterSubscribers`,
`leads`, plus optional taxonomies (`authors`, `categories`). Each collection
pushes updates to the matching Supabase table via `afterChange` hooks that
reuse the shared PostgreSQL `Pool`.
- Localization is enabled for user-facing text fields so the SPA can render
`pt-BR` and `en` copy without code changes. Slugs, booleans, and select lists
(icons, gradients) enforce validation consistent with frontend expectations.
- Seed recommendations: create at least two `solutions` (with features array),
three `homepageFeatures` rows ordered for the landing page carousel, and seed
`teamMembers`/`repositories` with the profiles already present in Supabase to
avoid duplicate inserts when the hooks run.
- Follow-ups:
- Extend the Supabase `solutions` table with a `gradient` column and update
the SPA to consume it instead of falling back to hard-coded styles.
- Expose `siteSettings` records through the frontend for dynamic contact
metadata and gradient overrides sourced from Payload.
- Add automated deletion hooks (or manual SOP) so removing a document from
Payload also removes the Supabase row when appropriate.

## Shared frontend data layer (2025-03-01)
- Supabase read/write helpers now live in `src/lib/data/supabase.ts` with
generated types (`src/lib/supabase/types.gen.ts`). Run
`npm run supabase:types` after schema changes to regenerate typings.
- React code should consume data through the helpers (e.g.
`fetchSolutions`, `createLead`, `fetchLocalizedCopy`) instead of calling the
Supabase client directly. Use `useDynamicCopy` to merge CMS-managed strings
into i18n resources at runtime.
- CMS preview URLs are wired via `cms/src/utilities/preview.ts` so editors can
open SPA/Next routes for blog posts, solutions, home content, and site
settings.

## Status log (2025-02-14)
- Environment state: Local PostgreSQL 16 instance installed for disposable
verification; no background services left running after dropping the
`monynha_tmp` database.
- Schema status: All SQL migrations apply cleanly in timestamp order when run via
`npx supabase migration up --db-url postgresql://postgres:postgres@127.0.0.1:5432/monynha_tmp`.
- Next stage owner: Web platform team to replay the migrations in managed
Supabase projects and run the CMS ➜ Supabase ➜ frontend publishing smoke test.

## Security & access QA (2025-02-20)
- RPC `get_admin_dashboard_data` enforces admin-only reads (non-admin sessions receive `42501`).
- Admin dashboard requires `aal2` when a TOTP factor exists; after `challengeAndVerify`, leads/newsletter tables load successfully.
- Payload role transitions now emit webhooks to `payload-admin-sync`, updating `profiles.payload_user_id` and issuing password resets for new admins.

### Outstanding follow-up
- Populate `public.payload_admin_sync_config` with the deployed edge-function URL and secret in each Supabase environment.
- Deploy `supabase/functions/payload-admin-sync` with the required environment variables (`PAYLOAD_API_BASE_URL`, `PAYLOAD_ADMIN_TOKEN`, etc.).
- Perform an end-to-end CMS role promotion/demotion against a real Payload instance once the webhook endpoint is live.

## QA & Observability (2025-10-18)
- Automated coverage now includes:
- Unit tests for Payload ➜ Supabase hooks (`cms/__tests__/solutions.hook.unit.test.ts`).
- Integration checks for row-level security definitions (`tests/supabase/policies.integration.test.ts`).
- End-to-end SPA navigation and lead capture (`tests/e2e/spa.user-journeys.e2e.test.tsx`).
- Accessibility regression guard for the Solutions catalog (`tests/accessibility/solutions.a11y.test.tsx`).
- Monitoring endpoints:
- CMS sync events emit to `CMS_OBSERVABILITY_WEBHOOK_URL` with dashboards discoverable via `CMS_OBSERVABILITY_DASHBOARD_URL`.
- Supabase `payload-admin-sync` forwards status updates to `OBSERVABILITY_WEBHOOK_URL` and links back to the same observability dashboard.
- Release workflow:
- GitHub Actions `deploy_spa` (environment `spa-production`) archives the Vite bundle and requires approval before execution.
- GitHub Actions `deploy_cms` (environment `cms-production`) builds the Payload TypeScript output and likewise pauses for approval.
- Runbook snapshot:
1. Execute `npm test` locally to validate CMS hooks, policies, SPA journeys, and a11y gates.
2. Merge to `prod`; obtain approvals for both `spa-production` and `cms-production` environments inside the workflow run.
3. Monitor the observability dashboard for `payload-admin-sync` success or error logs immediately after release.
37 changes: 37 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# syntax=docker/dockerfile:1.4

FROM node:20-bullseye-slim AS base
WORKDIR /app
ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1

COPY package.json package-lock.json ./
COPY cms/package.json cms/package.json
COPY cms/package-lock.json cms/package-lock.json

RUN npm ci \
&& npm --prefix cms ci

COPY . .

RUN npm run build \
&& npm run cms:build

FROM node:20-bullseye-slim AS runner
WORKDIR /app
ENV NODE_ENV=production \
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 \
NPM_CONFIG_LOGLEVEL=warn

COPY --from=base /app/package.json ./
COPY --from=base /app/package-lock.json ./
COPY --from=base /app/node_modules ./node_modules
COPY --from=base /app/dist ./dist
COPY --from=base /app/scripts ./scripts
COPY --from=base /app/vite.config.ts ./vite.config.ts
COPY --from=base /app/tsconfig.json ./tsconfig.json
COPY --from=base /app/tsconfig.app.json ./tsconfig.app.json
COPY --from=base /app/tsconfig.node.json ./tsconfig.node.json

EXPOSE 4173

CMD ["npm", "start"]
78 changes: 65 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,53 @@ Monynha Softwares Web Spark is a demo web application built with **React**, **Vi
```sh
npm install
```
2. Create a `.env` file based on `.env.example` and provide your Supabase credentials.
2. Create matching environment files for the frontend and CMS workspaces.
```sh
cp .env.example .env
# edit .env and set VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY
cp cms/.env.example cms/.env
# edit both files and populate the required values listed below
```
3. Start the development server
3. Install the CMS dependencies (they live in a separate workspace).
```sh
npm --prefix cms install
```
4. Start the development server
```sh
npm run dev
```

The application will be available on [http://localhost:5173](http://localhost:5173) by default.

To boot Payload locally run the shared script from the repository root:

```sh
npm run cms:dev
```

## Docker & Nixpacks

Builds for containerised environments are orchestrated with
[Nixpacks](https://nixpacks.com/) and the provided `Dockerfile`:

1. Build an OCI image (requires the Nixpacks CLI).
```sh
nixpacks build . --config nixpacks.toml --name monynha-web
```
2. Run the container, injecting the same environment variables you would use
locally.
```sh
docker run --rm -p 4173:4173 --env-file .env monynha-web
```

The generated image executes `npm start`, which serves the production Vite
bundle through a lightweight preview server bound to `0.0.0.0`. You can also
build the repository with a plain Docker workflow:

```sh
docker build -t monynha-web .
docker run --rm -p 4173:4173 monynha-web
```

## Folder structure

```
Expand All @@ -35,23 +70,40 @@ src/

## Scripts

- `npm run dev` – start the development server
- `npm run lint` – run ESLint
- `npm run dev` – start the frontend development server
- `npm run lint` – run ESLint across the frontend workspace
- `npm run cms:dev` – run the Payload CMS development server
- `npm run cms:lint` – type-check the CMS workspace with TypeScript
- `npm run cms:build` – compile the CMS TypeScript sources
- `npm run test` – run unit tests (none at the moment)
- `npm run build` – create a production build
- `npm run build` – create a production build of the frontend
- `npm start` – serve the production build (used by Docker/Nixpacks)
- `npm run sitemap` – generate `public/sitemap.xml`

### Environment variables

Create a `.env` file in the project root with the following entries so the
Supabase client can connect to your instance:
Populate the following variables in `.env` to configure the frontend app and
automation scripts:

```bash
VITE_SUPABASE_URL=<your-supabase-url>
VITE_SUPABASE_ANON_KEY=<your-anon-key>
```
| Variable | Purpose |
| --- | --- |
| `VITE_SUPABASE_URL` | Supabase instance URL used by the frontend client. |
| `VITE_SUPABASE_ANON_KEY` | Supabase anon key exposed to the browser. |
| `SITE_URL` | Canonical site URL used when generating the sitemap. |
| `SUPABASE_PROJECT_ID` | Supabase project identifier for external tooling. |
| `SUPABASE_SERVICE_ROLE_KEY` | Service role key for server-to-server jobs. |

The CMS workspace (`cms/.env`) requires its own secrets:

| Variable | Purpose |
| --- | --- |
| `PAYLOAD_SECRET` | Secret string for signing Payload authentication tokens. |
| `PAYLOAD_PUBLIC_SERVER_URL` | Public URL used by Payload when generating links. |
| `DATABASE_URL` | Postgres connection string shared with Supabase. |

## Authentication & Security

These variables match the placeholders in `.env.example`.
- [Authentication and security flows](docs/auth-flows.md): password reset lifecycle, dashboard MFA management, the admin RPC, and the Payload provisioning webhook.

## Technologies

Expand Down
4 changes: 4 additions & 0 deletions cms/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Payload CMS
PAYLOAD_SECRET=
PAYLOAD_PUBLIC_SERVER_URL=
DATABASE_URL=
Loading