{"id":15046889,"url":"https://github.com/heydoctor/copyful","last_synced_at":"2025-10-28T19:31:48.165Z","repository":{"id":40828258,"uuid":"260573506","full_name":"heydoctor/copyful","owner":"heydoctor","description":"✏️ Microcopy management, simplified","archived":false,"fork":false,"pushed_at":"2023-07-18T22:20:57.000Z","size":1075,"stargazers_count":6,"open_issues_count":26,"forks_count":0,"subscribers_count":32,"default_branch":"main","last_synced_at":"2024-09-25T03:04:48.202Z","etag":null,"topics":["contentful","hooks","microcopy","react"],"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/heydoctor.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":null,"support":null}},"created_at":"2020-05-01T22:51:50.000Z","updated_at":"2021-06-29T22:42:52.000Z","dependencies_parsed_at":"2023-02-18T04:45:56.403Z","dependency_job_id":null,"html_url":"https://github.com/heydoctor/copyful","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heydoctor%2Fcopyful","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heydoctor%2Fcopyful/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heydoctor%2Fcopyful/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heydoctor%2Fcopyful/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/heydoctor","download_url":"https://codeload.github.com/heydoctor/copyful/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219875834,"owners_count":16554708,"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":["contentful","hooks","microcopy","react"],"created_at":"2024-09-24T20:53:42.619Z","updated_at":"2025-10-28T19:31:47.831Z","avatar_url":"https://github.com/heydoctor.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ✏️ Copyful\n\n[![codecov](https://codecov.io/gh/heydoctor/copyful/branch/master/graph/badge.svg?token=KRQ62D1GW7)](https://codecov.io/gh/heydoctor/copyful)\n[![npm](https://img.shields.io/npm/v/copyful.svg)](https://www.npmjs.com/package/copyful)\n[![npm](https://img.shields.io/npm/dm/copyful.svg)](https://npm-stat.com/charts.html?package=copyful\u0026from=2017-05-19)\n[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-prettier-brightgreen.svg)](http://standardjs.com/)\n[![MIT License](https://img.shields.io/npm/l/copyful.svg?style=flat-square)](https://github.com/heydoctor/copyful/blob/master/LICENSE)\n\nStatically, or dynamically, pull in product microcopy from a version controlled third party.\n\nProduct copy can become difficult to manage across product platforms as well as internal design and engineering tooling. Copy changes frequently and for many reasons (more clarity, typo, legal guidance, etc...) and engineering **must** be involved to make these changes. Sometimes the changes aren't straightforward - it becomes a hunt across repositories or copy has drifted across our web and native applications.\n\nCopyful simplifies copy management by providing a simple way to consume and distribute copy across react applications.\n\n## Usage\n\nInstall with npm or yarn.\n\n```\nnpm install copyful\nyarn add copyful\n```\n\nInstantiate Copyful with `createCopyful`.\n\n```tsx\nimport React from 'react';\nimport { createCopyful } from './Copyful';\n\nconst copy = {\n  header: {\n    title: 'Welcome to {pageTitle}',\n    subtitle: 'Freerange Organic Copy Management'\n  }\n}\n\nexport const {\n  CopyfulProvider,\n  useCopy\n} = createCopyful(copy);\n\nfunction App() {\n  return (\n    \u003cCopyfulProvider\u003e\n      \u003cHeaderSection /\u003e\n    \u003c/CopyfulProvider\u003e\n  );\n}\n```\n\n### Hooks\n\n```tsx\nfunction HeaderSection() {\n  const context = {\n    pageTitle: 'Copyful',\n  };\n\n  const { title, subtitle } = useCopy('header', context);\n\n  return (\n    \u003cheader className=\"header-section\"\u003e\n      \u003ch1\u003e{title}\u003c/h1\u003e\n      \u003ch2\u003e{subtitle}\u003c/h2\u003e\n    \u003c/header\u003e\n  );\n}\n```\n\n### Render Prop\n\n```tsx\nfunction HeaderSection() {\n  return (\n    \u003cCopyful copyKey=\"header\" context={{ pageTitle: 'Copyful' }}\u003e\n      {({ title, subtitle }) =\u003e (\n        \u003cheader className=\"header-section\"\u003e\n          \u003ch1\u003e{title}\u003c/h1\u003e\n          \u003ch2\u003e{subtitle}\u003c/h2\u003e\n        \u003c/header\u003e\n      )}\n    \u003c/Copyful\u003e\n  );\n}\n```\n\n### Example\n\nCheckout `/example` for a working react app using Copyful, or pull down the repo and play with it locally\n'yarn example'\n\n## Remote Sources\n\nCopyful also has built in support for pulling down your copy from remote sources via its CLI. To begin, it only has support for [Contentful](https://www.contentful.com) but in an extensisble and modular fashion, such that it should be easy to add other _adapters_ like Google Sheets or any other headless CMS.\n\n### How It Works\n\nThe Copyful CLI will pull down the content from your remote source and transform it into a consistent structure we can recognize. The resulting output is a dynamically generated .js/.ts file so the typing may be inferred when importing and creating the `copyful` instance referenced above.\n\n```ts\ninterface Copyful {\n  [locale: string]: {\n    [category: string]: {\n      [name: string]: string;\n    };\n  };\n}\n\n// path-you-provided.ts\nexport const copy = {\n  'en-us': {\n    hero: {\n      tagline: 'Easy, affordable, and secure online medical visits.',\n    },\n  },\n};\n```\n\n### Commands\n\n#### `clone`\n\n- `adapter` _string_ The remote source you want to pull from. Defaults to `contentful`\n- `path` _string_ The filepath in which you want the copy to be written to\n\n```sh\n$ npx copyful clone --adapter \u003cadapter\u003e --path app/assets/copy.js\n```\n\n### Sources\n\n\u003e Notes on any nuances or unique considerations for remote sources\n\n##### Contentful\n\nWhen cloning, ensure that `COPYFUL_CONTENTFUL_SPACE` and `COPYFUL_CONTENTFUL_ACCESS_TOKEN` are populated in your environment. Initially, we're quite opinionated on the data structure, both in Contentful and the resulting generated copy file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fheydoctor%2Fcopyful","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fheydoctor%2Fcopyful","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fheydoctor%2Fcopyful/lists"}