{"id":35528172,"url":"https://github.com/code-wheel/jsonapi-frontend","last_synced_at":"2026-01-13T23:33:13.898Z","repository":{"id":331416336,"uuid":"1126532937","full_name":"code-wheel/jsonapi-frontend","owner":"code-wheel","description":"Drupal module: path → JSON:API URL resolver for headless \u0026 hybrid frontends (Next.js, Astro, Nuxt, Remix).","archived":false,"fork":false,"pushed_at":"2026-01-04T02:52:33.000Z","size":131,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-07T23:52:10.025Z","etag":null,"topics":["astro","decoupled","drupal","headless","jsonapi","nextjs","nuxt","remix"],"latest_commit_sha":null,"homepage":"https://www.drupal.org/project/jsonapi_frontend","language":"PHP","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/code-wheel.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"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":"2026-01-02T05:18:28.000Z","updated_at":"2026-01-04T02:23:09.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/code-wheel/jsonapi-frontend","commit_stats":null,"previous_names":["code-wheel/jsonapi-frontend-drupal"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/code-wheel/jsonapi-frontend","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/code-wheel%2Fjsonapi-frontend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/code-wheel%2Fjsonapi-frontend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/code-wheel%2Fjsonapi-frontend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/code-wheel%2Fjsonapi-frontend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/code-wheel","download_url":"https://codeload.github.com/code-wheel/jsonapi-frontend/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/code-wheel%2Fjsonapi-frontend/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28399508,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"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":["astro","decoupled","drupal","headless","jsonapi","nextjs","nuxt","remix"],"created_at":"2026-01-04T01:15:53.692Z","updated_at":"2026-01-13T23:33:13.892Z","avatar_url":"https://github.com/code-wheel.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# JSON:API Frontend\n\n[![Drupal Module](https://github.com/code-wheel/jsonapi-frontend/actions/workflows/drupal-module.yml/badge.svg?branch=master)](https://github.com/code-wheel/jsonapi-frontend/actions/workflows/drupal-module.yml?query=branch%3Amaster) [![Semgrep](https://github.com/code-wheel/jsonapi-frontend/actions/workflows/semgrep.yml/badge.svg?branch=master)](https://github.com/code-wheel/jsonapi-frontend/actions/workflows/semgrep.yml?query=branch%3Amaster) [![codecov](https://codecov.io/gh/code-wheel/jsonapi-frontend/branch/master/graph/badge.svg)](https://codecov.io/gh/code-wheel/jsonapi-frontend) [![Security Policy](https://img.shields.io/badge/security-policy-blue.svg)](SECURITY.md)\n\n`jsonapi_frontend` is a minimal Drupal module that makes JSON:API frontend-ready by adding a **path → JSON:API URL** resolver endpoint.\n\n- Resolve frontend paths (including aliases) to JSON:API resource URLs\n- Optional Redirect support (honors `redirect` module; returns 301/302 info)\n- Hybrid headless: choose what your frontend renders vs what stays on Drupal\n- Optional Views support via `jsonapi_views`\n- Optional secret-protected routes feed (`/jsonapi/routes`) for static builds (SSG)\n- Optional cache revalidation webhooks for frontend caches (Next.js, etc.)\n- Optional menu endpoint (`/jsonapi/menu/{menu}`) via `jsonapi_frontend_menu`\n\nDocumentation: https://www.drupal.org/docs/contributed-modules/jsonapi-frontend\nIssue queue: https://www.drupal.org/project/issues/jsonapi_frontend\n\n## Requirements\n\n- Drupal 10 or 11\n- Core modules: JSON:API, Path Alias\n\nOptional:\n- [`jsonapi_views`](https://www.drupal.org/project/jsonapi_views) (Views support)\n\n## Install\n\n```bash\ncomposer require drupal/jsonapi_frontend\ndrush en jsonapi_frontend\n```\n\n## Try it\n\n```bash\ncurl \"https://your-site.com/jsonapi/resolve?path=/about-us\u0026_format=json\"\n```\n\nTypical successful entity resolution looks like:\n\n```json\n{\n  \"resolved\": true,\n  \"kind\": \"entity\",\n  \"jsonapi_url\": \"/jsonapi/node/page/…\",\n  \"headless\": true\n}\n```\n\n## Frontend usage\n\n### Option A: TypeScript client (optional)\n\n```bash\nnpm i @codewheel/jsonapi-frontend-client\n```\n\n```ts\nimport { resolvePath, fetchJsonApi } from \"@codewheel/jsonapi-frontend-client\"\n\nconst resolved = await resolvePath(\"/about-us\")\nif (resolved.resolved \u0026\u0026 resolved.kind === \"entity\") {\n  const doc = await fetchJsonApi(resolved.jsonapi_url)\n  console.log(doc.data)\n}\n```\n\n### Option B: Call the endpoint directly\n\n```ts\nconst resolved = await fetch(`${DRUPAL_BASE_URL}/jsonapi/resolve?path=${path}\u0026_format=json`).then((r) =\u003e r.json())\nif (resolved.resolved \u0026\u0026 resolved.kind === \"entity\") {\n  const doc = await fetch(`${DRUPAL_BASE_URL}${resolved.jsonapi_url}`).then((r) =\u003e r.json())\n}\n```\n\n### Starters (optional)\n\n- Next.js (routing + rendering + media helpers): https://github.com/code-wheel/jsonapi-frontend-next\n- Astro (SSR + optional proxy middleware): https://github.com/code-wheel/jsonapi-frontend-astro\n- Nuxt 3 + Remix recipes: see `MIGRATION.md`\n\n#### One-click deploy (Vercel)\n\n[![Deploy Next.js starter](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/code-wheel/jsonapi-frontend-next\u0026env=DRUPAL_BASE_URL\u0026envDescription=Drupal%20site%20URL%20(example%3A%20https%3A%2F%2Fwww.example.com)\u0026envLink=https%3A%2F%2Fgithub.com%2Fcode-wheel%2Fjsonapi-frontend-next%2Fblob%2Fmaster%2F.env.example)\n[![Deploy Astro starter](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/code-wheel/jsonapi-frontend-astro\u0026env=DRUPAL_BASE_URL\u0026envDescription=Drupal%20origin%20URL%20(example%3A%20https%3A%2F%2Fcms.example.com)\u0026envLink=https%3A%2F%2Fgithub.com%2Fcode-wheel%2Fjsonapi-frontend-astro%2Fblob%2Fmaster%2F.env.example)\n\n## Configuration\n\nConfigure at `/admin/config/services/jsonapi-frontend`.\n\nTypical settings:\n- Deployment mode (Split routing vs frontend-first)\n- Drupal URL / origin + optional proxy secret\n- Resolver cache max-age (anonymous-only)\n- Resolver langcode fallback (`site_default` or `current`)\n- Headless-enabled bundles (entities) and View displays\n\nFor deployment and migration examples, see `MIGRATION.md`.\n\n## Production checklist\n\n- Set “Drupal URL” so `drupal_url` is deterministic (don’t rely on Host headers).\n- Set `trusted_host_patterns` in `settings.php`.\n- If using `nextjs_first`, set `X-Proxy-Secret` and keep it in env/`settings.php` (not config exports).\n- Rate limit `/jsonapi/resolve*` and `/jsonapi/*` at the edge (Cloudflare/nginx) to prevent path brute-force load.\n- If using authenticated JSON:API, keep credentials server-side and never cache authenticated responses.\n- For Next.js images, restrict remote domains (`DRUPAL_IMAGE_DOMAIN` in the starter).\n\n## Supported content\n\n- **Entities:** any canonical content entity route exposed by JSON:API (nodes, terms, media, users, and custom entities)\n- **Views:** page displays with paths (requires `jsonapi_views`)\n- **Layout Builder:** hybrid mode (keep bundles non-headless) or true headless via the optional add-on `jsonapi_frontend_layout` (`/jsonapi/layout/resolve`). See `MIGRATION.md`.\n\n## Security notes\n\n- The resolver respects entity access; unpublished/restricted content resolves as “not found”.\n- Resolver caching is only applied for anonymous requests; authenticated requests return `Cache-Control: no-store`.\n- If you enable the routes feed (`/jsonapi/routes`), keep the secret in build-only env vars and don’t expose it to browsers.\n- For config-managed sites, secrets are stored outside config exports (state) and can be overridden in `settings.php`.\n- The endpoint lives under `/jsonapi/` so it can share the same perimeter rules you apply to JSON:API.\n- If you run “frontend-first”, you can protect the Drupal origin with a shared secret header.\n- If you want a fully hidden origin, you can also require the proxy secret for `/jsonapi/*` (server-side fetching only).\n- For authenticated JSON:API, keep credentials server-side (Basic/OAuth/JWT). Cookie-based writes require Drupal CSRF tokens (`/session/token`) and strict CORS.\n\n## Links\n\n- Migration guide: `MIGRATION.md`\n- Changelog: `CHANGELOG.md`\n- NPM client: https://www.npmjs.com/package/@codewheel/jsonapi-frontend-client\n- Starter: https://github.com/code-wheel/jsonapi-frontend-next\n- Menus (optional): https://www.drupal.org/project/jsonapi_frontend_menu\n- Webforms (optional): https://www.drupal.org/project/jsonapi_frontend_webform\n- Layout Builder (optional): https://www.drupal.org/project/jsonapi_frontend_layout\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcode-wheel%2Fjsonapi-frontend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcode-wheel%2Fjsonapi-frontend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcode-wheel%2Fjsonapi-frontend/lists"}