{"id":39075902,"url":"https://github.com/cloud-gov/pages-editor","last_synced_at":"2026-01-17T18:26:38.754Z","repository":{"id":273547067,"uuid":"918195191","full_name":"cloud-gov/pages-editor","owner":"cloud-gov","description":"Editor/Admin UI for interacting with Pages content","archived":false,"fork":false,"pushed_at":"2026-01-13T17:09:38.000Z","size":1725,"stargazers_count":2,"open_issues_count":47,"forks_count":3,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-01-13T19:20:35.533Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cloud-gov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-01-17T12:45:13.000Z","updated_at":"2026-01-08T21:15:44.000Z","dependencies_parsed_at":null,"dependency_job_id":"63b89c06-4705-49eb-a5e1-193768fdbc33","html_url":"https://github.com/cloud-gov/pages-editor","commit_stats":null,"previous_names":["cloud-gov/pages-editor"],"tags_count":0,"template":false,"template_full_name":"cloud-gov/.github","purl":"pkg:github/cloud-gov/pages-editor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-gov%2Fpages-editor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-gov%2Fpages-editor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-gov%2Fpages-editor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-gov%2Fpages-editor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cloud-gov","download_url":"https://codeload.github.com/cloud-gov/pages-editor/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-gov%2Fpages-editor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28515471,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T17:57:59.192Z","status":"ssl_error","status_checked_at":"2026-01-17T17:57:52.527Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-17T18:26:38.623Z","updated_at":"2026-01-17T18:26:38.716Z","avatar_url":"https://github.com/cloud-gov.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pages Editor\n\nA customized [Payload CMS](https://github.com/payloadcms/payload) editor for creating and managing federal websites.\n\n## Initial Goals\n\nContent Editors can:\n\n- Edit via WYSIWIG Editor\n- Avoid login through Github\n- Perform basic user management and editorial workflow functions\n\n## Second Goals\n\n- Basic asset management\n- Access Modules/Blocks/Pre-configured units of content\n- Edit non-Post pages\n\n## Development\n\n### Running Locally\n\nWe use docker compose to setup the environment and run all of the supporting services to properly run this locally.\nWe have created some package.json scripts to make running the docker commands a bit easier.\n\nDocker compose will provide hardcoded PAYLOAD_API_KEY and EDITOR_APP_URL to the pages-site-gantry service.\n\n#### Get and build docker images\n`npm run dc:build`\n\n#### install node deps\n`npm run dc:install`\n\n#### Run the database migration and seed the database\n*Note: running the seed script will output bot API keys for you to use in the pages-site-gantry*\n`npm run dc:seed`\n\n#### Launch the app locally\n`npm run dc:up`\n\nAfter this, the editor is available at localhost:3000/admin; the first load will take a few seconds while the app is compiled.\n\nThe database is seeded with the following for local development:\n\n- Three sites, one of which is a \"dummy\" site for admins\n- At least five users:\n  - `admin@gsa.gov`: Global admin representing a Pages operator\n  - `site1manager@gsa.gov`, `site2manager@gsa.gov`: Website managers with access to one site each.\n  - `site1user@gsa.gov`, `site2user@gsa.gov`: Website users with access to one site each.\n  - By default, sites create a `bot` user with read-only access to site data.\n  - To login as a user, use the password `password`\n\n#### Local Live Preview\n\nUsing the local seed (`npm run dc:seed`) command creates the live preview experience locally for the two sites in our docker compose services. We build the main branch of [pages-site-gantry](https://github.com/cloud-gov/pages-site-gantry) in the [docker/Dockerfile-pages-site-gantry)](./docker/Dockerfile-pages-site-gantry) and we use hardcoded `PAYLOAD_API_KEY` keys to ensure both sites are accessible from the admin dashboard live preview.\n\n#### Seeding and Exporting Data\n\nThe `npm run dc:seed` command seeds the database with initial data including sites, users, and collection content. For global data (like Home Page, Menu, Footer, PreFooter, and Site Config), you can export the current state from a running instance:\n\n```bash\n# Export global data to seed files\nnpm run export:globals\n```\n\nThis command exports the current state of all global collections to `scripts/datasets/globals/` directory. These exported files are then used by the seed script to populate globals when running `npm run dc:seed`.\n\n**Note:** The `export:globals` command only handles global types. Collection data (like Pages, Posts, Events, etc.) is managed separately and seeded from the dataset files in `scripts/datasets/collections/`.\n\nTo update seed data:\n1. Make changes to globals in the admin UI or via API\n2. Run `npm run export:globals` to capture the current state\n3. Commit the updated seed files\n4. Future `npm run dc:seed` runs will use the updated data\n\n### Creating database migrations\n\nIf you want the database schema to change, you will need to update the schema by adjusting or adding to the collections/globals.\nRunning the seed and creating the migrations in specific orders will make development faster and simpler.\n\nBefore you start update the database schema, make sure you get the lastest database changes locally.\n\n```bash\n# Refresh the db, run the migrations, and seed the db\nnpm run dc:seed\n\n# Check the migrations status\nnpm run dc:migrate:status\n```\n\nNext you will want to edit or add to the existing schema in collections/globals. After you have made the update you can generate and run the migrations.\n\n```bash\n# Create a migration and give it a name to describe the migration using snake case with underscores\nnpm run dc:migrate:create a_name_describing_the_migration\n\n# Run the migration up to verify it runs\nnpm run dc:migrate:up\n\n# Run the migration down to verify it reverts back\nnpm run dc:migrate:down\n\n# Run the migration up again to reverify\nnpm run dc:migrate:up\n```\n\nIf you want to make adjustments to the schema as you are working locally, you should check the migration status `npm run dc:migrate:status` and make sure it has not been run. If it has, run `npm run dc:migrate:down`. Next, get rid of the generated migrations you have created. You can run `git restore src/migrations/.`. Then adjust the collections/globals and go throught the migration gerneration process again.\n\nOnce you like the status of the migration, make sure to run `npm run dc:generate:types` to generate the related typescript types of the schema.\n\n**Note: If you are weary of a migration, you can push the branch up but do not create a Pull Request. When a Pull Request is created, the development env will run the migrations and deploy the app. Ask for additional engineering eyes to help confirm the update.\n\n### Infrastructure Notes\n\n- Based on the Payload CMS [website template](https://github.com/payloadcms/payload/tree/main/templates/website)\n- Written as a mult-tenant application similar to the [Payload example](https://github.com/payloadcms/payload/tree/main/examples/multi-tenant) but customized for certain necessary patterns:\n  - Full tenant isolation (the payload example allows users to view the tenant access of other users)\n  - Site managers can add users. Attempting to add existing users alters their `sites` property rather than erroring.\n  - Custom site/roles display (ongoing)\n  - ...\n- Relies on [pages-site-gantry](https://github.com/cloud-gov/pages-site-gantry) for live previewing\n\n### Cloud Foundry Setup\n\nThis repository's CI deploys the `pages-editor-((env))` application and [`pages-site-gantry`](https://github.com/cloud-gov/pages-site-gantry) deploys the preview application. There are four other services which are manually created per-environment:\n\n| name                          | service                     | plan           | notes                                                                                                                                     |\n| ----------------------------- | --------------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |\n| pages-editor-((env))-rds      | aws-rds                     | micro-psql     | Primary database                                                                                                                          |\n| pages-editor-((env))-deployer | cloud-gov-service-account   | space-deployer | [Create account](https://cloud.gov/docs/services/cloud-gov-service-account/). Add these credentials to cred-hub                           |\n| pages-editor-((env))-auth     | cloud-gov-identity-provider | oauth-client   | [Create the service](https://cloud.gov/docs/services/cloud-gov-identity-provider/). Add these credentials to `pages-editor-((env))-creds` |\n| pages-editor-((env))-creds    | user-provided               |                | Credentials here are captured in the `.profile` script for different applications                                                         |\n| pages-editor-((env))-s3       | pages-s3                    | basic-vpc      | Used for storing site information to be passed on to Concourse                                                                            |\n| publisher-((env))-domain      | external-domain             | domain-with-cdn| Set the domain \"pubisher((env-postfix)).cloud.gov and forward_headers to \"Authorization\" to allow for API Key access                      |\n\nEach environment has a network access policy for sending email per [these instructions](https://github.com/cloud-gov/pages-mailer/?tab=readme-ov-file#usage) (make sure to specify additional ports if needed to match the `EMAIL_HOST` environment variable)\n\n### Bootstrapping an instance\n\nTo bootstrap a new instance, you can SSH into the running Cloud Foundry application and run the bootstrap script:\n\n1. SSH into the app instance:\n   ```bash\n   cf ssh pages-editor-((env))\n   ```\n\n2. Boot the runtime and get a bash shell:\n   ```bash\n   /tmp/lifecycle/launcher /home/vcap/app bash ''\n   ```\n\n3. Run the bootstrap script with the admin email:\n   ```bash\n   npx payload run scripts/bootstrap.ts admin@example.gov\n   ```\n\nThis will initialize the database with the necessary seed data and create the initial admin user.\n\n### Test framework and structure\n\n#### DB Tests\n\nWe currently run a series of access controls tests against our database using various users. Access control is implement via [Payload properties](https://payloadcms.com/docs/access-control/overview) and custom functions we've written in `src/access`. A requirement of this application is that site data is made available only to appropriate users; these tests are essential to making that guarantee. Tests are located at `src/collections/**/access.test.ts`\n\nTests are run with `vitest` via:\n\n```sh\n# Run tests and watch for changes to rerun on file update\nnpm run dc:test\n\n# Run tests and exit\nnpm run dc:test:ci\n```\n\nWe make extensive use of [vitest context and fixtures](https://vitest.dev/guide/test-context.html) in our tests. Important notes:\n\n- Each test runs as a [separate transaction](test/utils/test.ts#L6-10): all fixtures are scoped to that transaction, the transaction id is passed to the test, and all DB operations should use that transaction id to guarantee they are operating on the correct data and are correctly removed at the end of the test.\n- The transaction id and `sites` are [automatic fixtures](https://vitest.dev/guide/test-context.html#automatic-fixture) and are available for every test. For other fixtures, ensure that the fixture variable is passed as part of the destructed test context for it to be initialized. E.g.\n\n        ```ts\n        test('my test needs posts', async ({ tid, posts }) =\u003e ...\n        ```\n\n  Currently available fixtures are shown at `test/utils/context.types.ts`.\n\n  - These fixtures can be overwritten or modified for a given `describe` block by using `test.scoped`. Modified values will be passed down to any dependent fixtures (e.g. `defaultUserRole` will update `testUser` accordingly). Note that this is only available in a pre-release version of `vitest` (`\"^3.1.0-beta.2\"`).\n\n- The test database is cleared (`test/utils/globalSetup.ts`) before and after each test-suite run to ensure accurate fixtures.\n\n#### UI Tests\n\nTBD\n\n#### API Tests\n\nTBD\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloud-gov%2Fpages-editor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloud-gov%2Fpages-editor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloud-gov%2Fpages-editor/lists"}