{"id":28249964,"url":"https://github.com/cambis/whero","last_synced_at":"2026-05-02T01:34:57.685Z","repository":{"id":39440447,"uuid":"498586916","full_name":"Cambis/whero","owner":"Cambis","description":"NextJS DatoCMS boilerplate","archived":false,"fork":false,"pushed_at":"2022-06-01T04:40:43.000Z","size":202,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-02T01:34:55.804Z","etag":null,"topics":["datocms","nextjs"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Cambis.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-06-01T04:13:01.000Z","updated_at":"2022-06-01T04:41:48.000Z","dependencies_parsed_at":"2022-08-23T14:20:53.769Z","dependency_job_id":null,"html_url":"https://github.com/Cambis/whero","commit_stats":null,"previous_names":[],"tags_count":2,"template":true,"template_full_name":null,"purl":"pkg:github/Cambis/whero","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cambis%2Fwhero","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cambis%2Fwhero/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cambis%2Fwhero/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cambis%2Fwhero/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Cambis","download_url":"https://codeload.github.com/Cambis/whero/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cambis%2Fwhero/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32520156,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-02T01:12:54.858Z","status":"ssl_error","status_checked_at":"2026-05-02T01:12:54.261Z","response_time":64,"last_error":"SSL_read: 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":["datocms","nextjs"],"created_at":"2025-05-19T13:16:14.165Z","updated_at":"2026-05-02T01:34:57.670Z","avatar_url":"https://github.com/Cambis.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Whero - NextJS 12.x DatoCMS Boilerplate\n\nThis is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).\n\n## What Is Included\n\n- Docker\n- Typescript\n- ESLint\n- Prettier\n- Stylelint\n- Sentry issue tracking\n- Bugherd integration\n- Strict content security policy\n- Security headers\n- Mailcatcher\n- Sitemap generation\n- Automatic environment configuration for Github Codespaces\n- Github actions\n- Semantic versioning\n- Husky and lint-staged\n- And much more!\n\n## Installation\n\nGenerate a new repository using the [Use this template](https://github.com/Cambis/whero/generate) function in Github.\n\nIn the package.json change the project name to an appropiate name for your project.\nAlso a good idea to search for all uses of `whero` and change them to a short version of you app name. These changes are in the docker files, mainly the sync config.\n\nFinally, reset the version number inside the package.json to 0.1.0.\n\n## Getting Started\nIf you are developing this project with codespaces (recommended), you can skip straight [this section](#running-the-project).\n\n### Prerequisites\n\n- [Docker-Compose](https://docs.docker.com/compose/install/)\n- [Docker-Sync](https://docker-sync.readthedocs.io/en/latest/getting-started/installation.html) (for MacOSX only)\n\n### Docker World\n\nThis project uses three custom docker images for development inside `./docker`.\n\n```sh\ntukutuku (web) # An alpine image that contains node\nkaihopu (mailcatcher) # An alpine image that contains mailcatcher\n```\n\n### Set up environment variables\n\nFirst, copy the example graphql types:\n```bash\ncp src/templates/graphql.ts.example src/lib/graphql.ts\n```\n\nIn your DatoCMS' project, go to the **Settings** menu at the top and click **API tokens**.\n\nThen click **Read-only API token** and copy the token.\n\nCopy the `.env.example` file in this directory to `.env` (if it hasn't been created already):\n\n```bash\ncp .env.example .env\n```\n\nThen set each variable on `.env`:\n\n- `NEXT_DATOCMS_API_TOKEN` should be the API token you just copied.\n- `NEXT_DATOCMS_PREVIEW_SECRET` can be any random string (but avoid spaces), like `MY_SECRET` - this is used for the Preview Mode](https://www.datocms.com/docs/next-js/setting-up-next-js-preview-mode).\n\nYour `.env` file should look like this:\n\n```bash\nNEXT_DATOCMS_API_TOKEN=...\nNEXT_DATOCMS_PREVIEW_SECRET=...\n...\n```\n\n### Running the Project\n\nFirst, run the development server:\n\n#### Codespaces\n\n```bash\ndocker-compose up\n```\n\n#### Linux\n\n```bash\ndocker-compose build\ndocker-compose run --rm --no-deps --entrypoint=\"\" web yarn\ndocker-compose up\n```\n\n#### MacOSX\n\n```bash\ndocker-compose build\ndocker-sync start\ndocker-compose -f docker-compose.yml -f docker-compose-dev.yml run --rm --no-deps --entrypoint=\"\" web yarn\ndocker-sync-stack start\n```\n\nOpen [http://localhost:3000](http://localhost:3000) with your browser to see the result.\n\nYou can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.\n\nIf you are redirected to `pages/static/index.tsx` you will need to run the default migrations.\n\n[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.\n\nThe `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.\n\n## Learn More\n\nTo learn more about Next.js, take a look at the following resources:\n\n- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.\n- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.\n\nYou can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!\n\n## Deploy on Vercel\n\nThe easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template\u0026filter=next.js\u0026utm_source=create-next-app\u0026utm_campaign=create-next-app-readme) from the creators of Next.js.\n\nCheck out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.\n\n## Directory Structure\n\n```bash\nsrc\n├── components # Contains JSX elements\n│   ├── {component} # Name of JSX element\n│   │   ├── {component}.tsx # Contains the definition of the element\n│   │   ├── index.ts # Exports the element\n│   │   └── types.d.ts # Contains the type definitions for the element\n│   └── index.ts # Imports/exports all the JSX elements\n├── graphql # Contains GraphQL queries\n│   ├── {record_type} # Record to be queried\n│   │   ├── {recordQuery}.gql # Contains the actual query definition\n│   │   └── {recordFields}.fragment.gql # Fragment containing the queryable fields of a record\n└── lib # Shared/global functions go here\n├── pages # Pages go here\n│   ├── api\n│   │   └── {function}.ts\n│   ├── _app.tsx\n│   └── index.tsx\n└── styles # Styles go here\n    └── globals.css\n```\n\n## Migrations\n\nThis project uses DatoCMS migrations to track content type changes and updates. For more information check the [DatoCMS documentation](https://www.datocms.com/docs/scripting-migrations/scripting-migrations-with-the-datocms-cli).\n\nFirst exec into the web container while it is running:\n\n```bash\ndocker-compose exec web /bin/sh # Linux/codespaces\ndocker-compose -f docker-compose.yml -f docker-compose-dev.yml exec web /bin/sh # MacOSX\n```\n\nCreate a new migration with the included template:\n\n```bash\ndato new migration 'create my pages etc' --migrationTemplate=./src/templates/defaultPageMigration.js\n```\n\nRun the migration on a new environment:\n\n```bash\ndato migrate --destination=feature-my-new-migration\n```\n\nLog into DatoCMS and promote the new environment.\n\n## Linting\n\nThis project uses Prettier, ESLint, Stylelint and Husky.\n\nHusky will lint all staged files in commits. To skip husky add the `--no-verify` flag to your git command.\n\n_Deploys must pass lint testing before release._\n\nYou can run linting manually:\n\n```bash\n# Assuming your project is currently running...\ndocker-compose exec web yarn lint # Linux/Codespaces\ndocker-compose -f docker-compose.yml -f docker-compose-dev.yml exec web yarn lint # Mac\n```\n\nMost basic lint errors can be fixed via:\n\n```bash\n# Assuming your project is currently running...\ndocker-compose exec web yarn lint:fix # Linux/Codespaces\ndocker-compose -f docker-compose.yml -f docker-compose-dev.yml exec web yarn lint:fix # Mac\n```\n\nCheck the `package.json` to see additional scripts\n\n### Stylelint\n\nSince Stylelint 14.x VSCode has required extra configuration to make it work with the official extension. Inside your `.vscode/settings.json` you should have this:\n\n```json\n{\n  \"css.validate\": false,\n  \"scss.validate\": false,\n  \"stylelint.validate\": [\"css\", \"less\", \"postcss\", \"scss\"]\n}\n```\n\nThis tells VSCode to use the extension to validate css/scss.\n\nIf you are running this project in codespaces this should be already configured for you.\n\n## Form Submissions\n\nEnsure you have these fields in your .env:\nConsult the vercel instance for the recaptcha keys.\n\n```sh\nSMTP_PORT=1025\nSMTP_HOST=mailcatcher\nSMTP_USERNAME=user\nSMTP_PASSWORD=password\nSMTP_TO=bar@example.com\nSMTP_FROM=foo@example.com\n\nNEXT_PUBLIC_RECAPTCHA_SITE_KEY=\nNEXT_RECAPTCHA_SECRET_KEY=\n\nNEXT_CORS_ALLOWLIST=http://localhost:3000, http://127.0.0.1:3000\n\n# `openssl rand -base64 48`\nNEXT_JWT_SECRET=\n```\n\nThe base example form lies with `pages/static/contact/index.tsx`\n\nAll forms should submit to `pages/api/forms/notifications`\n\nThe form will only send data to DatoCMS in production mode.\n\nLocal submissions are caught by mailcatcher, open [http://localhost:1080](http://localhost:1080) with your browser to see the results.\n\nForm submission is divied between two endpoints, `/api/forms/notfications` and `/api/forms/submissions` respectively.\nThe former is used to notify admins of submissions via email, the latter is used to store submissions in DatoCMS.\n\n### Form Submission Models\n\nEach form must have its own submission model in DatoCMS. These models are used to track submissions. The naming convention is `submission_\u003cFORM_NAME\u003e`.\nEach model must contain the following fields:\n\n```ts\ninterface SubmissionModel {\n  firstName: string; // Single-line string\n  lastName: string; // Single-line string\n  email: string; // Single-line string\n  content: string; // Multiple-paragraph text\n  attachements?: File[]; // Asset gallery\n  values: any; // JSON\n}\n```\n\n### Middleware\n\nThe form endpoints use express-style middleware to modify and validate each incoming request, they are called using the `runMiddleware()` function. Each function must extend the `NextApiMiddlewareHandler` function type.\n\n### JWT Authentication\n\nThe `submissions` endpoint is protected by a JWT token. This token is generated from the `NEXT_JWT_SECRET` .env variable. Tokens are generated and authenticated internally only.\n\n## Content Security Policy\n\nThis project employs a content security policy. which is update inside of `next.config.js`. Due to the static generation of the site there is currently no robust way to employ a strict content security policy with hashes or noncing.\n\n## Sentry\n\nThis project is preconfigured to run on Sentry. To configure, first create a project in Sentry, then use the provided dsn to fill these .env values:\n\n```bash\nSENTRY_DSN=you-dsn-goes-here\nNEXT_PUBLIC_SENTRY_DSN=you-dsn-goes-here\nSENTRY_ORG=your-org\nSENTRY_PROJECT=your-project-name\nSENTRY_REPORTING_URI=\nSENTRY_AUTH_TOKEN= # not neccessary for local\n```\n\nThen update the project name in `sentry.properties` to the name of the project in Sentry.\n\n## Bugherd\n\nThis project is preconfigured to run with Bugherd. To configure, first create a project in Bugherd and add the provided api key to the .env:\n\n```bash\nNEXT_PUBLIC_BUGHERD_KEY=you-key-goes-here\n```\n\n## Sitemap\n\nThis project uses [next-sitemap](https://www.npmjs.com/package/next-sitemap) to generate sitemap at post-build time. Configuration is located inside `next-sitemap.js`, consult the next-sitemap repository for the configuration options.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcambis%2Fwhero","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcambis%2Fwhero","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcambis%2Fwhero/lists"}