{"id":20237131,"url":"https://github.com/blinkk/amagaki-plugin-google-sheets","last_synced_at":"2026-05-10T11:45:36.952Z","repository":{"id":43167521,"uuid":"361248174","full_name":"blinkk/amagaki-plugin-google-sheets","owner":"blinkk","description":"Amagaki plugin that provides Google Sheets integration for content management. Store website copy in a Google Sheet and consume it within an Amagaki project.","archived":false,"fork":false,"pushed_at":"2022-10-31T15:46:07.000Z","size":762,"stargazers_count":0,"open_issues_count":5,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-25T16:39:19.201Z","etag":null,"topics":["amagaki","cms","google-sheets"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blinkk.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-04-24T19:24:30.000Z","updated_at":"2022-01-15T00:58:51.000Z","dependencies_parsed_at":"2023-01-20T04:47:48.883Z","dependency_job_id":null,"html_url":"https://github.com/blinkk/amagaki-plugin-google-sheets","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blinkk%2Famagaki-plugin-google-sheets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blinkk%2Famagaki-plugin-google-sheets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blinkk%2Famagaki-plugin-google-sheets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blinkk%2Famagaki-plugin-google-sheets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blinkk","download_url":"https://codeload.github.com/blinkk/amagaki-plugin-google-sheets/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241681432,"owners_count":20002311,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["amagaki","cms","google-sheets"],"created_at":"2024-11-14T08:24:54.985Z","updated_at":"2026-05-10T11:45:31.899Z","avatar_url":"https://github.com/blinkk.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# amagaki-plugin-google-sheets\n\n[![NPM Version][npm-image]][npm-url]\n[![GitHub Actions][github-image]][github-url]\n[![TypeScript Style Guide][gts-image]][gts-url]\n\nAn Amagaki plugin for fetching content from Google Sheets. Capable of\ntransforming Google Sheets into various formats, and supports using Google\nSheets for managing translations.\n\nUse this to allow non-developers to manage content (including website copy,\ndata, and translations) in a Google Sheet, and consuming that content within\nyour Amagaki project to build a website.\n\n## Usage\n\n1. Install the plugin.\n\n```shell\nnpm install --save @amagaki/amagaki-plugin-google-sheets\n```\n\n2. Authenticate. See [authentication](#authentication) for details.\n\n3. Add to `amagaki.ts`.\n\n```typescript\nimport {GoogleSheetsPlugin} from '@amagaki/amagaki-plugin-google-sheets';\nimport {Pod, ServerPlugin} from '@amagaki/amagaki';\n\nexport default (pod: Pod) =\u003e {\n  // Run Google Sheets plugin when dev server starts.\n  const serverPlugin = pod.plugins.get('ServerPlugin') as ServerPlugin;\n  serverPlugin.register(async () =\u003e {\n    const sheets = GoogleSheetsPlugin.register(pod);\n\n    await Promise.all([\n      // Binds a collection to specified tabs within the Google Sheet. Deletes\n      // files from the collection that no longer exist in the sheet.\n      // Because the `transform` value is set to `strings`, the plugin will also\n      // import any translations contained within the sheets to their respective\n      // locale files.\n      sheets.bindCollection({\n        collectionPath: '/content/strings',\n        spreadsheetId: '1qP7IPYJ1nIA5useXKbm8nHyj96Ue_6YMEFkwgpUoL-c',\n        ranges: ['homepage', 'about'],\n        transform: 'strings',\n      }),\n\n      // Saves a single file, \"homepage\" tab, `strings` transformation.\n      sheets.saveFile({\n        podPath: '/content/partials/homepage.yaml',\n        spreadsheetId: '1qP7IPYJ1nIA5useXKbm8nHyj96Ue_6YMEFkwgpUoL-c',\n        range: 'homepage',\n        transform: 'strings',\n      }),\n\n      // Save a single file, \"about\" tab, `grid` transformation.\n      sheets.saveFile({\n        podPath: '/content/partials/about.yaml',\n        spreadsheetId: '1qP7IPYJ1nIA5useXKbm8nHyj96Ue_6YMEFkwgpUoL-c',\n        range: 'about',\n        transform: 'grid',\n      }),\n\n      // Save a single file, \"about\" tab, `objectRows` transformation.\n      sheets.saveFile({\n        podPath: '/content/partials/aboutObjectRows.yaml',\n        spreadsheetId: '1qP7IPYJ1nIA5useXKbm8nHyj96Ue_6YMEFkwgpUoL-c',\n        range: 'about',\n        transform: 'objectRows',\n      }),\n    ]);\n  });\n};\n```\n\n## Transform options\n\n- [amagaki-plugin-google-sheets](#amagaki-plugin-google-sheets)\n  - [Usage](#usage)\n  - [Transform options](#transform-options)\n    - [strings](#strings)\n      - [Types](#types)\n    - [grid](#grid)\n    - [objectRows](#objectrows)\n    - [rows (default)](#rows-default)\n  - [Authentication](#authentication)\n    - [Option 1: Using application default credentials](#option-1-using-application-default-credentials)\n    - [Option 2: Using a service account key file](#option-2-using-a-service-account-key-file)\n\n### strings\n\nUse the `strings` format when managing website copy (and optionally translation\nstrings) inside a Google Sheet. Non-translation data can also be added, by\nleaving the `type` field blank. For data that shouldn't fallback to the default\n`en` locale, use `explicit` in the `type` field.\n\nConverts a sheet formatted as a grid of strings into a mapping of keys to\nlocalized strings. Additional non-string types can be added to manage localized\ndata. The sheet must be in the following format:\n\n```markdown\n| key | type         | en                  | de                 | es                 |\n| --- | ------------ | ------------------- | ------------------ | ------------------ |\n| foo | string       | Hello               | Hallo              | Hola               |\n| bar | string       | Bye                 | Tschüss            | Adiós              |\n| bar | preferString | Goodbye             |                    |                    |\n| baz |              | https://example.com | https://example.de | https://example.es |\n| qux | explicit     | a                   | b                  |                    |\n| qaz | capitalize   | a                   | b                  | c                  |\n```\n\nThe values are transformed to\\*:\n\n```yaml\nfoo: !pod.string Hello\nbar: !pod.string\n  prefer: Goodbye\n  value: Bye\nbaz: !IfLocale\n  default: https://example.com\n  de: https://example.de\n  es: https://example.es\nqux: !IfLocale\n  en: a\n  de: b\nqaz: !IfLocale\n  en: A\n  de: B\n  es: C\n```\n\nFurthermore, any translation strings denoted by type \"string\" within the sheet\nare automatically saved to the pod's locale files. Any rows that do not have\ntype \"string\" are not imported to the locale files.\n\nTo refer to your Google Sheets data from documents, use the `!pod.yaml` YAML\ntype. The content can be accessed in a template regularly. `!pod.string` types\nare automatically translated, and `!IfLocale` types are automatically localized.\n\n```yaml\npartials:\n  - partial: hero\n    headline: !pod.yaml /content/strings/homepage.yaml?foo\n    body: !pod.yaml /content/strings/homepage.yaml?bar\n    button:\n      url: !pod.yaml /content/strings/homepage.yaml?baz\n```\n\n_NOTE: This example includes a sample `capitalize` custom cell type. See below\nfor details on using custom cell types._\n\n#### Types\n\nIn the `strings` transformation, the `type` cell supports serialization as follows:\n\n- `string`: `!pod.string` objects\n- `preferString`: `!pod.string` objects, with the value used as the preferred default string\n- `explicit`: `!IfLocale` localized data, where blank values do not fall back\n- `(blank)`: `!IfLocale` localized data, where blank values fall back to the default locale\n\nYou can define a custom cell type – your own serialization function to transform\nthe data within a cell:\n\n1. Choose a name for the function.\n2. Use this name for the value of the `type` cell.\n3. Use the `addCellType` method on the plugin to register your type.\n\n```typescript\nconst sheets = GoogleSheetsPlugin.register(pod);\nsheets.addCellType('capitalize', (data: string) =\u003e {\n  return data.toUpperCase();\n});\n```\n\nCustom cell types can also be used with the `objectRows` and `grid` transformations by specifying which header cells correspond to which cell types:\n\n1. Use `addCellType` to register the cell type with a name.\n2. When calling `saveFile` or `bindCollection`, supply a mapping of header cells to named cell types. See example below.\n\n```\nsheets.saveFile({\n  podPath: '/content/partials/about.yaml',\n  spreadsheetId: '1qP7IPYJ1nIA5useXKbm8nHyj96Ue_6YMEFkwgpUoL-c',\n  range: 'about',\n  transform: 'grid',\n  columnsToCellTypes: {\n    // Use the `capitalize` cell type for all cells with header `header1`.\n    header1: 'capitalize',\n  }\n}),\n```\n\n### grid\n\nConverts a sheet formatted as a grid of strings into a mapping of keys to\nheaders to values. The sheet must be in the following format:\n\n```\n| \u003cBLANK\u003e | header1 | header2 |\n| ------- | ------- | ------- |\n| foo     | a       | b       |\n| bar     | c       | d       |\n```\n\nThe values are transformed to:\n\n```yaml\nfoo:\n  header1: a\n  header2: b\nbar:\n  header1: c\n  header2: d\n```\n\n### objectRows\n\nConverts a sheet formatted as a grid of strings into a list of objects\nmapping headers to values. The sheet must be in the following format:\n\n```\n| header1 | header2 | header3 |\n| ------- | ------- | ------- |\n| foo     | a       | b       |\n| bar     | c       | d       |\n```\n\nThe values are transformed to:\n\n```yaml\n- header1: foo\n  header2: a\n  header3: b\n- header1: bar\n  header2: c\n  header3: d\n```\n\n### rows (default)\n\nDoes not modify response from Google Sheets. The sheet is simply serialized as a\nlist of lists.\n\n```\n| header1 | header2 | header3 |\n| ------- | ------- | ------- |\n| foo     | a       | b       |\n| bar     | c       | d       |\n```\n\nThe values are transformed to:\n\n```yaml\n- - header1\n  - header2\n  - header3\n- - foo\n  - a\n  - b\n- - bar\n  - c\n  - d\n```\n\n## Authentication\n\nThere are two ways to authenticate. We recommend using the application default\nidentity (option 1), but using a service account key file is acceptable as well.\n\n### Option 1: Using application default credentials\n\n1. Install the `gcloud SDK`. [See instructions](https://cloud.google.com/sdk/docs/downloads-interactive).\\*\n2. Login and set the application default credentials. Ensure you provide the required scopes.\n\n```bash\ngcloud auth application-default login \\\n  --scopes=openid,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/spreadsheets\n```\n\n3. That's it! Now, Amagaki will use the signed in Google Account to fetch content.\n\n\\*NOTE: If you've never authenticated using `gcloud` before, after installing the SDK, you may need to set a default Google Cloud project. Use the command below after installing the `gcloud SDK`:\n\n```bash\n# Replace $PROJECT with your GCP project ID.\ngcloud auth login\ngcloud config set project $PROJECT\ngcloud auth application-default set-quota-project $PROJECT\n```\n\n### Option 2: Using a service account key file\n\n1. Acquire a service account key file. You can do this interactively, from the IAM section of the Google Cloud Console, or you can do this via the `gcloud` CLI (see below for an example).\n\n```bash\nPROJECT=\u003cGoogle Cloud Project ID\u003e\n\n# Create a service account named `amagaki`.\ngcloud --project=$PROJECT \\\n  iam service-accounts create \\\n  amagaki\n\n# Create a JSON key and download it to `key.json`.\ngcloud --project=$PROJECT \\\n  iam service-accounts keys create \\\n  --iam-account amagaki@$PROJECT.iam.gserviceaccount.com \\\n  key.json\n```\n\n2. Ensure `key.json` is added to your `.gitignore`.\n3. Ensure the sheet is shared with the service account.\n4. Pass `keyFile` to the sheets plugin.\n\n```typescript\nGoogleSheetsPlugin.register(pod, {\n  keyFile: 'key.json',\n});\n```\n\n[github-image]: https://github.com/blinkk/amagaki-plugin-google-sheets/workflows/Run%20tests/badge.svg\n[github-url]: https://github.com/blinkk/amagaki-plugin-google-sheets/actions\n[npm-image]: https://img.shields.io/npm/v/@amagaki/amagaki-plugin-google-sheets.svg\n[npm-url]: https://npmjs.org/package/@amagaki/amagaki-plugin-google-sheets\n[gts-image]: https://img.shields.io/badge/code%20style-google-blueviolet.svg\n[gts-url]: https://github.com/google/gts\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblinkk%2Famagaki-plugin-google-sheets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblinkk%2Famagaki-plugin-google-sheets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblinkk%2Famagaki-plugin-google-sheets/lists"}