{"id":23993153,"url":"https://github.com/franciscomoretti/mdcast","last_synced_at":"2026-02-19T05:33:22.863Z","repository":{"id":200291058,"uuid":"677517380","full_name":"FranciscoMoretti/mdcast","owner":"FranciscoMoretti","description":"Post Markdown articles to Medium, Dev.to and Hashnode","archived":false,"fork":false,"pushed_at":"2025-01-25T09:18:39.000Z","size":553,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-31T14:18:38.212Z","etag":null,"topics":["blog","cross-post","cross-posting","devto","devto-api","hashnode","hashnode-api","markdown","md","medium","medium-ap"],"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/FranciscoMoretti.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-08-11T19:26:59.000Z","updated_at":"2025-10-06T13:18:45.000Z","dependencies_parsed_at":"2025-04-14T18:23:06.318Z","dependency_job_id":"8b3e5cbc-9405-4cfc-afbf-f29d64465a28","html_url":"https://github.com/FranciscoMoretti/mdcast","commit_stats":null,"previous_names":["franciscomoretti/md-cross-post","franciscomoretti/mdcast"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/FranciscoMoretti/mdcast","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FranciscoMoretti%2Fmdcast","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FranciscoMoretti%2Fmdcast/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FranciscoMoretti%2Fmdcast/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FranciscoMoretti%2Fmdcast/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FranciscoMoretti","download_url":"https://codeload.github.com/FranciscoMoretti/mdcast/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FranciscoMoretti%2Fmdcast/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29604552,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T05:11:50.834Z","status":"ssl_error","status_checked_at":"2026-02-19T05:11:38.921Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: 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":["blog","cross-post","cross-posting","devto","devto-api","hashnode","hashnode-api","markdown","md","medium","medium-ap"],"created_at":"2025-01-07T20:55:30.457Z","updated_at":"2026-02-19T05:33:17.854Z","avatar_url":"https://github.com/FranciscoMoretti.png","language":"TypeScript","readme":"# mdcast\n\nA CLI tool to cross post Markdown articles into Medium, Dev.to and Hashnode.\n\n## Installation\n\n```bash\nnpm install mdcast\n```\n\n## Usage\n\n### 1. Initialize Configuration\n\nFirst, initialize your project configuration:\n\n```bash\nmdcast init\n```\n\nThis will create a `mdcast.config.json` file in your current directory with default settings.\n\n### 2. Set Environment Variables\n\nCreate a `.env` file with your API keys (see Configuration Instructions below for details):\n\n```env\n# Required for Dev.to\nDEVTO_API_KEY=your_api_key\nDEVTO_ORG_ID=optional_org_id\n\n# Required for Hashnode\nHASHNODE_TOKEN=your_token\nHASHNODE_PUB_ID=optional_pub_id\n\n# Required for Medium\nMEDIUM_TOKEN=your_token\nMEDIUM_PUBLICATION_NAME=optional_pub_name\n```\n\n### 3. Post Your Content\n\nTo post your markdown content:\n\n```bash\nmdcast post path/to/your/article.md --platforms devto,medium,hashnode\n```\n\nOptions:\n\n- `--platforms`: Comma-separated list of platforms to post to (`devto`, `medium`, `hashnode`)\n- `--dry-run`: Test the posting process without actually publishing\n\n## Configuration\n\nYou can customize your posting preferences in `mdcast.config.json`:\n\n```json\n{\n  \"devto\": {\n    \"should_publish\": true\n  },\n  \"hashnode\": {\n    \"should_hide\": false,\n    \"tags_dictionary\": {}\n  },\n  \"medium\": {\n    \"should_publish\": true,\n    \"should_notify_followers\": false,\n    \"tags_dictionary\": {}\n  },\n  \"markdown\": {\n    \"frontmatterProperties\": {\n      \"title\": \"title\",\n      \"description\": \"description\",\n      \"canonical_url\": \"canonical_url\",\n      \"tags\": \"tags\",\n      \"image\": \"image\",\n      \"date\": \"date\",\n      \"slug\": \"slug\"\n    },\n    \"link_url_base\": \"\",\n    \"canonical_url_base\": \"\",\n    \"image_url_base\": \"\"\n  }\n}\n```\n\n## References\n\n- [Medium API](https://github.com/Medium/medium-api-docs)\n- [Dev.to API](https://developers.forem.com/api)\n- [Hashnode API](https://api.hashnode.com/)\n\n### Configuration Instructions\n\nThis README provides instructions for configuring API keys and IDs required for publishing articles on different platforms. Please follow the guidelines below to set up the necessary credentials:\n\n#### Dev.to\n\n- **DEVTO_API_KEY (Required):** Your personal Dev.to API key is necessary for authentication. To obtain your API key go to the Settings \u003e Extensions section of your account [here](https://dev.to/settings/extensions).\n\n- **DEVTO_ORG_ID (Optional):** The ID of the organization under which you want to publish the article. You can find this ID in two ways:\n  1.  From the organization dashboard page, where the ID is the last part of the URL. (e.g., `https://dev.to/dashboard/organization/ORG_ID`).\n  2.  Alternatively, you can use the Dev.to List Organizations endpoint to discover the ID.\n\n#### Dev.to sanitized gifs (Optional)\n\nDev.to has a file size limit for GIF uploads. To work around this, you can upload your GIFs to Giphy first and use the Giphy URL in your posts instead.\n\n- **GIPHY_API_KEY_DEVTO_GIFS (Optional):** The Giphy API key is required for uploading GIFs to Giphy. You can obtain this key by following [this link](https://developers.giphy.com/dashboard/).\n\n#### Hashnode\n\n- **HASHNODE_TOKEN (Required):** Your Hashnode personal token is essential for authentication. Ensure you have this token readily available.\n\n- **HASHNODE_PUB_ID (Optional):** The ID of the publication where you wish to publish the article can be found in publication's dashboard page, where the ID is the second part of the URL (e.g., `https://hashnode.com/PUB_ID/dashboard`).\n\n### Medium\n\n- **MEDIUM_TOKEN (Required):** The Medium Integration Token is required for authentication. You can obtain this token by following [this link](https://medium.com/me/settings/security).\n\n- **MEDIUM_PUBLICATION_NAME (Optional):** Specify the exact name of the Medium publication where you want to publish the article. Make sure it matches the publication name on Medium.\n\nPlease ensure you have the required credentials and follow the respective links provided to retrieve them.\n\n#### Medium Tables with nice formatting (Optional)\n\nMedium does not support tables in markdown, so we need to use a gist to save the table content. GitHub gists provide a nice markdown table formatting. If not provided, the table will be saved as a markdown codeblock.\n\n- **GITHUB_TOKEN_MEDIUM_TABLES (Optional):** The GitHub token is required for the Medium client to create a gist and save the table content as a markdown file. You can obtain this token by following [this link](https://github.com/settings/tokens).\n\nYou'll need to:\n\n1. Create a GitHub Personal Access Token (PAT) with gist scope at https://github.com/settings/tokens\n2. Add it to your .env file as GITHUB_TOKEN_MEDIUM_TABLES or similar\n\n## Tags Configuration\n\nEach platform requires specific tag formats. You can configure tag mappings in your `mdcast.config.json` under the `tags_dictionary` field for each platform:\n\n### Hashnode Tags\n\nTo get tag IDs for Hashnode:\n\n1. Find the tag slug (e.g., \"Shadcn UI\" -\u003e \"shadcn-ui\")\n2. Query the Hashnode GraphQL API at https://gql.hashnode.com:\n   ```graphql\n   query {\n     tag(slug: \"shadcn-ui\") {\n       id\n     }\n   }\n   ```\n3. Add to config:\n   ```json\n   \"hashnode\": {\n     \"tags_dictionary\": {\n       \"Shadcn UI\": {\n         \"slug\": \"shadcn-ui\",\n         \"id\": \"648b5554f9b78f110ed2c1eb\"\n       }\n     }\n   }\n   ```\n\n### Medium Tags\n\nTo get tag slugs for Medium:\n\n1. Search for the tag on Medium (e.g., \"Shadcn UI\")\n2. Get the slug from the URL: `https://medium.com/tag/shadcn-ui` -\u003e `shadcn-ui`\n3. Add to config:\n   ```json\n   \"medium\": {\n     \"tags_dictionary\": {\n       \"Shadcn UI\": {\n         \"slug\": \"shadcn-ui\"\n       }\n     }\n   }\n   ```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffranciscomoretti%2Fmdcast","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffranciscomoretti%2Fmdcast","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffranciscomoretti%2Fmdcast/lists"}