{"id":35528173,"url":"https://github.com/code-wheel/jsonapi-frontend-astro","last_synced_at":"2026-01-13T23:40:01.428Z","repository":{"id":331422897,"uuid":"1126077999","full_name":"code-wheel/jsonapi-frontend-astro","owner":"code-wheel","description":"Astro starter for Drupal JSON:API with jsonapi_frontend","archived":false,"fork":false,"pushed_at":"2026-01-04T02:23:28.000Z","size":551,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-08T02:46:09.393Z","etag":null,"topics":["astro","decoupled","drupal","headless","jsonapi","starter-template"],"latest_commit_sha":null,"homepage":"https://www.drupal.org/project/jsonapi_frontend","language":"TypeScript","has_issues":true,"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":null,"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-01T03:35:33.000Z","updated_at":"2026-01-04T02:23:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/code-wheel/jsonapi-frontend-astro","commit_stats":null,"previous_names":["code-wheel/jsonapi-frontend-astro"],"tags_count":1,"template":true,"template_full_name":null,"purl":"pkg:github/code-wheel/jsonapi-frontend-astro","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/code-wheel%2Fjsonapi-frontend-astro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/code-wheel%2Fjsonapi-frontend-astro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/code-wheel%2Fjsonapi-frontend-astro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/code-wheel%2Fjsonapi-frontend-astro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/code-wheel","download_url":"https://codeload.github.com/code-wheel/jsonapi-frontend-astro/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/code-wheel%2Fjsonapi-frontend-astro/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","starter-template"],"created_at":"2026-01-04T01:15:54.029Z","updated_at":"2026-01-13T23:40:01.423Z","avatar_url":"https://github.com/code-wheel.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jsonapi-frontend-astro\n\n[![Deploy with Vercel](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) [![CI](https://github.com/code-wheel/jsonapi-frontend-astro/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/code-wheel/jsonapi-frontend-astro/actions/workflows/ci.yml?query=branch%3Amaster) [![CodeQL](https://github.com/code-wheel/jsonapi-frontend-astro/actions/workflows/codeql.yml/badge.svg?branch=master)](https://github.com/code-wheel/jsonapi-frontend-astro/actions/workflows/codeql.yml?query=branch%3Amaster) [![Security Policy](https://img.shields.io/badge/security-policy-blue.svg)](SECURITY.md)\n\nAstro starter template for Drupal JSON:API with [`jsonapi_frontend`](https://www.drupal.org/project/jsonapi_frontend).\n\n## One-click deploy (free)\n\nClick the button above, set `DRUPAL_BASE_URL`, and deploy.\n\n## Quick start (local)\n\n1) Use this template (optional)\n\nClick the green **\"Use this template\"** button above, or:\n\n```bash\ngh repo create my-site --template code-wheel/jsonapi-frontend-astro\ncd my-site\n```\n\n1) Install dependencies\n\n```bash\nnpm install\n```\n\n2) Configure Drupal URL\n\n```bash\ncp .env.example .env\n```\n\nEdit `.env`:\n\n```env\nDRUPAL_BASE_URL=https://your-drupal-origin.com\n```\n\n3) Start developing\n\n```bash\nnpm run dev\n```\n\nOpen `http://localhost:4321` and navigate to any path that exists in Drupal.\n\n## Requirements\n\n- Node.js 22+\n- A Drupal 10+ site with:\n  - `drupal/jsonapi_frontend` enabled\n  - Core `jsonapi` enabled\n  - `jsonapi_views` (optional, for Views support)\n\n## How it works\n\n```\nRequest: /about-us\n  ↓\nResolver: GET {DRUPAL_BASE_URL}/jsonapi/layout/resolve?path=/about-us\u0026_format=json (falls back to /jsonapi/resolve)\n  ↓\nResponse: { kind: \"entity\", jsonapi_url: \"/jsonapi/node/page/...\", headless: true }\n  ↓\nFetch: GET {DRUPAL_BASE_URL}/jsonapi/node/page/... (server-side)\n  ↓\nRender (Astro SSR): /src/pages/[...slug].astro\n```\n\n## Layout Builder (optional)\n\nIf you use Drupal Layout Builder and want true headless rendering, install the add-on module:\n\n- Drupal: https://www.drupal.org/project/jsonapi_frontend_layout\n\nThis starter will then call:\n\n```bash\nGET /jsonapi/layout/resolve?path=/about-us\u0026_format=json\n```\n\nWhen the resolved entity is rendered with Layout Builder, the response includes a `layout` tree. This starter renders a minimal subset (field blocks only) and falls back to the normal entity renderer for everything else.\n\n## Minimal integration (without this starter)\n\nIf you prefer wiring this into an existing Astro project, the core loop is:\n\n```ts\nimport { resolvePath, fetchJsonApi, fetchView } from \"@codewheel/jsonapi-frontend-client\"\n\nconst baseUrl = import.meta.env.DRUPAL_BASE_URL\nconst resolved = await resolvePath(\"/about-us\", { baseUrl })\n\nif (resolved.resolved \u0026\u0026 resolved.kind === \"entity\" \u0026\u0026 resolved.jsonapi_url) {\n  const doc = await fetchJsonApi(resolved.jsonapi_url, { baseUrl })\n}\n\nif (resolved.resolved \u0026\u0026 resolved.kind === \"view\" \u0026\u0026 resolved.data_url) {\n  const doc = await fetchView(resolved.data_url, { baseUrl })\n}\n```\n\n## Deployment modes\n\n### Split routing (default)\n\n- Drupal stays on your main domain.\n- Your router/CDN sends selected paths to Astro.\n\n```env\nDEPLOYMENT_MODE=split_routing\nDRUPAL_BASE_URL=https://www.example.com\n```\n\n### Frontend-first (`nextjs_first`)\n\n- Astro handles all traffic on the main domain.\n- Drupal runs on an origin/subdomain (e.g. `https://cms.example.com`).\n- `src/middleware.ts` proxies:\n  - Drupal assets (`/sites`, `/core`, etc.)\n  - `/jsonapi/*` (so the API can live behind the same public domain)\n  - Webform routes like `/form/*` and `/webform_rest/*` (for interactive forms + submissions)\n  - any non-headless paths (based on `/jsonapi/resolve`)\n\n```env\nDEPLOYMENT_MODE=nextjs_first\nDRUPAL_BASE_URL=https://cms.example.com\nDRUPAL_ORIGIN_URL=https://cms.example.com\nDRUPAL_PROXY_SECRET=your-secret-from-drupal-admin\n```\n\nIn this mode, access Drupal admin directly on the origin domain (e.g. `https://cms.example.com/admin`).\n\n## Webforms (optional)\n\nDrupal Webform is usually best kept as a Drupal-rendered UI in hybrid headless setups:\n\n- **Split routing:** route `/form/*` to Drupal.\n- **Frontend-first:** this starter proxies `/form/*` and `/webform_rest/*` to Drupal (including POST submissions).\n\n## Static builds (SSG) (optional)\n\nThis starter runs in SSR mode by default (so it can support `nextjs_first` proxying). If you want Astro’s default static output (SSG), you still use `/jsonapi/resolve` for correctness — the missing piece is a build-time list of paths.\n\n- SSG works best with `split_routing` (static sites can’t proxy Drupal HTML).\n- Generate a route list from either:\n  - JSON:API collection endpoints (e.g. list `path.alias` from `/jsonapi/node/page?filter[status]=1\u0026fields[node--page]=path`), or\n  - the built-in routes feed (`/jsonapi/routes`) (recommended), or\n  - a single Views “routes feed” exposed via `jsonapi_views`.\n\nBuilt-in routes feed example:\n\n```bash\ncurl -H \"X-Routes-Secret: $ROUTES_FEED_SECRET\" \"https://cms.example.com/jsonapi/routes?_format=json\u0026page[limit]=50\"\n```\n\nExample `getStaticPaths()` (pre-render pages from `node--page`):\n\n```astro\n---\nimport { loadDrupalRoute } from \"../lib/drupal\"\n\nexport async function getStaticPaths() {\n  const baseUrl = import.meta.env.DRUPAL_BASE_URL\n  const url = new URL(\"/jsonapi/node/page\", baseUrl)\n  url.searchParams.set(\"filter[status]\", \"1\")\n  url.searchParams.set(\"fields[node--page]\", \"path\")\n  url.searchParams.set(\"page[limit]\", \"50\")\n\n  const doc = await fetch(url).then((r) =\u003e r.json())\n  const paths = (doc.data ?? [])\n    .map((node) =\u003e node?.attributes?.path?.alias)\n    .filter((p) =\u003e typeof p === \"string\" \u0026\u0026 p.startsWith(\"/\"))\n\n  return paths.map((p) =\u003e ({\n    params: { slug: p.split(\"/\").filter(Boolean) },\n    props: { path: p },\n  }))\n}\n\nconst { path } = Astro.props\nconst result = await loadDrupalRoute(path)\n---\n```\n\nIf you have a lot of content, paginate using JSON:API `links.next` (or `page[offset]`/`page[limit]`).\n\nSee the Migration Guide for details: https://www.drupal.org/docs/contributed-modules/jsonapi-frontend/migration-guide\n\n## Credentials (optional)\n\nIf your Drupal JSON:API requires auth, set one of these in `.env` (server-side only):\n\n- `DRUPAL_BASIC_USERNAME` + `DRUPAL_BASIC_PASSWORD`\n- `DRUPAL_JWT_TOKEN`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcode-wheel%2Fjsonapi-frontend-astro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcode-wheel%2Fjsonapi-frontend-astro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcode-wheel%2Fjsonapi-frontend-astro/lists"}