{"id":13807853,"url":"https://github.com/RobbieTheWagner/ember-meta","last_synced_at":"2025-05-14T00:32:10.889Z","repository":{"id":32028023,"uuid":"129610641","full_name":"RobbieTheWagner/ember-meta","owner":"RobbieTheWagner","description":"Setup meta for your Prember/Ember blog to support opengraph, microdata, Facebook, Twitter, Slack etc.","archived":false,"fork":false,"pushed_at":"2025-05-07T10:25:52.000Z","size":4655,"stargazers_count":19,"open_issues_count":15,"forks_count":6,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-07T11:30:10.735Z","etag":null,"topics":["blog","ember","meta","opengraph","prember","twitter"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/RobbieTheWagner.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-04-15T13:03:16.000Z","updated_at":"2025-05-07T10:24:17.000Z","dependencies_parsed_at":"2023-12-15T12:31:14.503Z","dependency_job_id":"9b7a9c0f-79a3-4b71-bb79-2cce7edebe32","html_url":"https://github.com/RobbieTheWagner/ember-meta","commit_stats":{"total_commits":460,"total_committers":5,"mean_commits":92.0,"dds":"0.17391304347826086","last_synced_commit":"dea80b2cd542fc388a67867854c89185a4945349"},"previous_names":["robbiethewagner/ember-meta","shipshapecode/ember-meta"],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobbieTheWagner%2Fember-meta","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobbieTheWagner%2Fember-meta/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobbieTheWagner%2Fember-meta/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobbieTheWagner%2Fember-meta/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RobbieTheWagner","download_url":"https://codeload.github.com/RobbieTheWagner/ember-meta/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254046417,"owners_count":22005591,"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":["blog","ember","meta","opengraph","prember","twitter"],"created_at":"2024-08-04T01:01:31.272Z","updated_at":"2025-05-14T00:32:05.878Z","avatar_url":"https://github.com/RobbieTheWagner.png","language":"JavaScript","funding_links":[],"categories":["Packages"],"sub_categories":["Static site generators \u0026 SEO"],"readme":"# ember-meta\n\n\u003ca href=\"https://shipshape.io/\"\u003e\u003cimg src=\"http://i.imgur.com/DWHQjA5.png\" width=\"100\" height=\"100\"/\u003e\u003c/a\u003e\n\n**[ember-meta is built and maintained by Ship Shape. Contact us for Ember.js consulting, development, and training for your project](https://shipshape.io/ember-consulting)**.\n\n[![npm version](https://badge.fury.io/js/ember-meta.svg)](http://badge.fury.io/js/ember-meta)\n![Download count all time](https://img.shields.io/npm/dt/ember-meta.svg)\n[![npm](https://img.shields.io/npm/dm/ember-meta.svg)]()\n[![Ember Observer Score](http://emberobserver.com/badges/ember-meta.svg)](http://emberobserver.com/addons/ember-meta)\n[![Build Status](https://travis-ci.org/shipshapecode/ember-meta.svg)](https://travis-ci.org/shipshapecode/ember-meta)\n\nSetup meta for your Prember/Ember blog to support opengraph, microdata, Facebook, Twitter, Slack etc.\n\n## Compatibility\n\n- Ember.js v4.4 or above\n- Ember CLI v4.4 or above\n- Node.js v16 or above\n\n## Installation\n\n```\nember install ember-meta\n```\n\n## Usage\n\nember-meta uses ember-cli-head under the hood, so to make sure your meta makes it into the `\u003chead\u003e` you will have to\nadd this to `application.hbs`:\n\n```hbs\n\u003cHeadLayout /\u003e\n```\n\nThis addon supports a config be set with the basic info for your blog, including the `title`,\n`description`, and `url`. The `url` should end in a trailing slash. These values will be used as defaults, and\nyou can override them by returning different values in your model.\n\n## Global Config\n\n```js\n// config/environment.js\nENV[\"ember-meta\"] = {\n  description:\n    \"Ramblings about Ember.js, JavaScript, life, liberty, and the pursuit of happiness.\",\n  imgSrc: \"http://i.imgur.com/KVqNjgO.png\",\n  siteName: \"Ship Shape\",\n  title: \"Blog - Ship Shape\",\n  twitterUsername: \"@shipshapecode\",\n  url: \"https://shipshape.io/blog/\",\n};\n```\n\nThe `title` will be used for both the `\u003ctitle\u003e` tag of your page, and for `og:title` and `twitter:title`. Similarly, the\ndescription will be used for `description`, `og:description`, and `twitter:description`. You probably are starting to see\na pattern forming here :smiley:.\n\nThe global config will be merged with the local config, when you are on a specific post. This allows you to define\nsane defaults, while also retaining the flexibility to override each value on a specific post, by defining it on the\n`model`.\n\nAll of the values, used to populate the meta, are computed properties, on the `head-data` service. This service is\nautomatically injected into all routes, and a default head.hbs is provided for you. This should allow a \"zero config\"\nsetup, if your app adheres to the same data formats as we expect.\n\n## Local Config\n\nThe preferred way of configuring ember-meta, is to set your values under the `metaInfo` property on your route.\nThis ensures you do not have potential naming conflicts for your meta when using a model.\n\n```js\n// routes/blog/post.js\nimport Route from \"@ember/routing/route\";\n\nexport default class BlogPost extends Route {\n  afterModel() {\n    super.afterModel(...arguments);\n\n    this.metaInfo = {\n      content:\n        \"\u003ch1\u003eEmber Inspector - The Journey so Far\u003c/h1\u003e \u003cp\u003eThis is a post body!\u003c/p\u003e\",\n      author: \"Robert Wagner\",\n      authorId: \"rwwagner90\",\n      categories: [\"ember\", \"ember.js\", \"ember inspector\"],\n      date: \"2018-04-09\",\n      slug: \"ember-inspector-the-journey-so-far\",\n      title: \"Ember Inspector - The Journey so Far\",\n    };\n  }\n}\n```\n\n### Using with a Vanilla Javascript Model Hook\n\nIf you want to override the global config, your `model()` hook must return an object with a certain format, i.e. an author\nname string, a categories array, a slug for the post, a title, content etc.\n\nHere is an example of a simple blog post using a POJO as the model:\n\n```js\n// routes/blog/post.js\nimport Route from \"@ember/routing/route\";\n\nexport default class BlogPost extends Route {\n  model() {\n    return {\n      content:\n        \"\u003ch1\u003eEmber Inspector - The Journey so Far\u003c/h1\u003e \u003cp\u003eThis is a post body!\u003c/p\u003e\",\n      author: \"Robert Wagner\",\n      authorId: \"rwwagner90\",\n      categories: [\"ember\", \"ember.js\", \"ember inspector\"],\n      date: \"2018-04-09\",\n      slug: \"ember-inspector-the-journey-so-far\",\n      title: \"Ember Inspector - The Journey so Far\",\n    };\n  }\n}\n```\n\n### Using with a Ember Data\n\nIf you are using Ember data it should work as expected. Here is an example of the same example using ember-data.\n\n```js\n// models/blog.js\nimport Model, { attr } from \"@ember-data/model\";\n\nexport default class Blog extends Model {\n  @attr content;\n  @attr author;\n  @attr categories;\n  @attr date;\n  @attr slug;\n  @attr title;\n}\n```\n\n```js\n// routes/blog/post.js\nimport Route from '@ember/routing/route';\n\nexport default BlogPost extends Route {\n  model() {\n    return this.store.findRecord('blog', 1);\n  }\n}\n```\n\n### Using with ember-cli-markdown-resolver\n\nIn this example, we are using [ember-cli-markdown-resolver](https://github.com/willviles/ember-cli-markdown-resolver)\nand it automatically will set the front matter values from your markdown as properties on your model, when you grab the file.\n\nThe values in my `.md` files look something like this:\n\n```md\n---\nauthor: Robert Wagner\nauthorId: rwwagner90\ncategories:\n  - ember\n  - ember.js\n  - ember inspector\ndate: \"2018-04-09\"\nslug: ember-inspector-the-journey-so-far\ntitle: Ember Inspector - The Journey so Far\n---\n```\n\n```js\n// routes/blog/post.js\nimport Route from \"@ember/routing/route\";\nimport { inject as service } from \"@ember/service\";\n\nexport default class BlogPost extends Route {\n  @service markdownResolver;\n\n  model({ path }) {\n    const withoutSlash = !path.endsWith(\"/\") ? path : path.slice(0, -1);\n    return this.markdownResolver.file(\"blog\", withoutSlash);\n  }\n}\n```\n\nIn this case we need to override the `head-data` service because ember-cli-markdown-resolver puts all of the\nfront-matter data under an `attributes` key.\n\n```js\n// services/head-data.js\nimport HeadDataService from \"ember-meta/services/head-data\";\nimport { computed } from \"@ember/object\";\nimport { getOwner } from \"@ember/application\";\n\nexport default class HeadData extends HeadDataService {\n  @computed(\"routeName\")\n  get currentRouteModel() {\n    return getOwner(this)\n      .lookup(`route:${this.get(\"routeName\")}`)\n      .get(\"currentModel.attributes\");\n  }\n\n  @computed(\"routeName\")\n  get content() {\n    // content is not on attributes when returned from ember-cli-markdown-resolver\n    return getOwner(this)\n      .lookup(`route:${this.get(\"routeName\")}`)\n      .get(\"currentModel.content\");\n  }\n}\n```\n\n## Advanced Local Config\n\n### Overriding Service Computed Properties\n\nSince all of this is powered by computed properties, in the `head-data` service. You can create your own head-data service, and\nextend the one we provide to override the computeds for various meta to do whatever you want.\n\n```js\n// services/head-data.js\nimport HeadDataService from \"ember-meta/services/head-data\";\nimport { computed } from \"@ember/object\";\n\nexport default class HeadData extends HeadDataService {\n  @computed(\"foo\")\n  get description() {\n    return this.foo.description;\n  }\n}\n```\n\n### Defining Your Own head.hbs\n\nA default `head.hbs` is automatically available to your app, but we also provide a blueprint, if you would like to manage the\ncontent yourself. This allows you to either define your own or delete it altogether and use the one we ship with this addon.\n\n## Contributing\n\nSee the [Contributing](CONTRIBUTING.md) guide for details.\n\n## License\n\nThis project is licensed under the [MIT License](LICENSE.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRobbieTheWagner%2Fember-meta","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRobbieTheWagner%2Fember-meta","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRobbieTheWagner%2Fember-meta/lists"}