{"id":23033698,"url":"https://github.com/sawyerclick/cmsvelte","last_synced_at":"2025-08-14T15:33:01.055Z","repository":{"id":43634030,"uuid":"462566948","full_name":"sawyerclick/CMSvelte","owner":"sawyerclick","description":"A Svelte template built with newsroom CMS's in mind ","archived":false,"fork":false,"pushed_at":"2024-01-03T17:36:44.000Z","size":4794,"stargazers_count":23,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-01-03T18:38:27.779Z","etag":null,"topics":["data-visualization","embeds","iframe","journalism","newsroom","svelte"],"latest_commit_sha":null,"homepage":"https://cmsvelte.s3.amazonaws.com/index.html","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sawyerclick.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2022-02-23T03:28:28.000Z","updated_at":"2023-10-13T05:15:06.000Z","dependencies_parsed_at":"2024-01-03T18:47:21.700Z","dependency_job_id":null,"html_url":"https://github.com/sawyerclick/CMSvelte","commit_stats":null,"previous_names":[],"tags_count":0,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sawyerclick%2FCMSvelte","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sawyerclick%2FCMSvelte/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sawyerclick%2FCMSvelte/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sawyerclick%2FCMSvelte/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sawyerclick","download_url":"https://codeload.github.com/sawyerclick/CMSvelte/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":229841489,"owners_count":18132566,"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":["data-visualization","embeds","iframe","journalism","newsroom","svelte"],"created_at":"2024-12-15T16:17:57.562Z","updated_at":"2024-12-15T16:17:58.009Z","avatar_url":"https://github.com/sawyerclick.png","language":"JavaScript","readme":"# **CMS**velte\n\nA [Svelte](https://svelte.dev/) starter template built with newsroom CMS's in mind. Dynamically create inline graphics based on the placement of `figure` elements with defined *data-cmsvelte* attributes.\n\nInspired by graphics rigs at Bloomberg, The Pudding, and The Wall Street Journal. Created with the help of [Kazi Awal](https://github.com/superKazi).\n\n *Previously known as tiny-svelte*.\n\n## Local env requirements\n\n- [Node 16 LTS](https://nodejs.org/dist/latest-v16.x/docs/api/)\n\n## Useful docs to features\n\n- [Svelte](https://svelte.dev/docs) as a component framework\n- [Vite](https://vitejs.dev/guide/) (with [Rollup](https://rollupjs.org/guide/en/) under the hood) for front-end tooling\n- [TailwindCSS](https://tailwindcss.com/) + [PostCSS](https://postcss.org/) for predefined styles, classes and syntax\n- [ArchieML](http://archieml.org/) as a micro-CMS powered by Google Docs\n- [ai2html](http://ai2html.org/) for responsive static images and charts\n- [D3](https://github.com/d3/d3) + [LayerCake](https://layercake.graphics/) for charting\n- [vite-imagetools](https://www.npmjs.com/package/vite-imagetools) for transforming images on the fly in Vite using Sharp\n\n### Quickstart\n\nUse [degit](https://www.npmjs.com/package/degit) to create a new repo using this one as a template.\n\n```bash\nnpx degit sawyerclick/cmsvelte my-cmsvelte\n```\n\n## Scripts\n\n### `npm run fetch:sheet`\n\nThis template has out-of-the-box features to help with consuming data from google sheets. Tag the Google Sheet for your graphic in `./config.json` and make sure you have the ID and sheet ID (gid) filled out correctly. Make sure the share permissions on the sheet are set up so that it is viewable by anyone with the share link. **Note: Don't make it available to edit by anybody!**\n\nDirectly import csv's into your .svelte file via [@rollup/plugin-dsv](https://www.npmjs.com/package/@rollup/plugin-dsv)\n\n```js\nimport data from '$lib/data/data.csv'\n```\n\n### `npm run fetch:copy`\n\nLike a lot of newsrooms, this uses a Google Doc and ArchieMl approach to make copy content management easier. The setup is similar to using Sheets data. Make sure the share permissions on the doc are set up so that it is viewable by anyone with the share link. Grab the document ID from the address bar — ...com/document/d/**1IiA5a5iCjbjOYvZVgPcjGzMy5PyfCzpPF-LnQdCdFI0**/edit — and paste it into the respective property in `./config.json`.\n\n[htmlparser2](https://www.npmjs.com/package/htmlparser2) and [html-entities](https://www.npmjs.com/package/html-entities) act as a middle man to catch various tags like `\u003ca\u003e`, `\u003ch*\u003e`, `\u003cul\u003e` and more.\n\nImport copy into your package like any JSON file\n\n```js\nimport copy from '$lib/data/copy.json'\n```\n\n## Development\n\n```shell\nnvm use\nnpm install\nnpm run dev\n```\n\nModify content in `src`.\n\n### Adding and removing graphics\n\nCMSvelte's power is dynamic placement unrestrained by content. After build, you can place the `\u003cfigure data-cmsvelte=\"CHART-ID\"\u003e` elements anywhere in the CMS and they will load.\n\nTo place graphics, edit `index.html` by adding or removing figures such as this: `\u003cfigure data-cmsvelte=\"CHART-ID\"\u003e\u003c/figure\u003e`. \n\nThen, in `src/main.ts`, import your wrapper component up top and add the applicable data to the component array. Every object in this array should have 1) a matching `\u003cfigure\u003e` element in index.html and 2) an imported component: \n\n```js\nconst components = [\n\t{\n\t\tchartID: 'CHART-ID',\n\t\tComponent: ImportedComponent,\n\t\tprops: {}\n\t},\n\t{\n\t\tchartID: 'CHART-ID2',\n\t\tComponent: ImportedComponent2,\n\t\tprops: {}\n\t},\n\t{\n\t\tchartID: 'CHART-ID3',\n\t\tComponent: ImportedComponent3,\n\t\tprops: {}\n\t},\n];\n```\n\n*Notes:* \n- High-level props can be passed down here as well using the `props: {}` object passed in MountComponent.\n\n### Writing styles\n\nIt's recommended to include the CMS's styles in a development environment and defer to them for fonts and classes to reduce the shipped CSS. This can be done by adding objects to a `cmsFiles` array in `main.ts`. This appends any tag and it's listed attributes to the `\u003chead\u003e` while in dev mode. These are not included in production.\n\nOtherwise, this template uses [Tailwind](https://tailwindcss.com/) for out-of-the-box classes that we don't have to think about. By default, these classes are prefixed with `cmsvelte-` to prevent clashing with CMS classes. This can be changed in `tailwind.config.cjs`. \n\nWrite global styles in `app.postcss`. Otherwise, use [Svelte's built-in scroped styling syntax](https://svelte.dev/tutorial/styling).\n\n### Asset management\n\nFor image optimization see [vite-imagetools](https://www.npmjs.com/package/vite-imagetools) or [sharp](https://www.npmjs.com/package/sharp).\n\n[Vite's Static Asset Handling](https://vitejs.dev/guide/assets.html) lets us import image and SVG files with several options. \n\n#### As files\n\nImports the hashed file name for the asset. For example, `imgUrl` will be `/img.png` during development, and become `/assets/img.2d8efhg.png` in the production build.\n\n```js\nimport imgUrl from '$lib/assets/img.png'\n```\n\n#### As strings\n\nImport raw strings by appending ?raw at the end. This is useful for SVG files.\n\n```js\nimport imgUrl from '$lib/assets/img.svg?raw'\n```\n\n### Useful libs\n\n- [body-scroll-lock](https://www.npmjs.com/package/body-scroll-lock) - Enables body scroll locking (for iOS Mobile and Tablet, Android, desktop Safari/Chrome/Firefox) without breaking scrolling of a target element (eg. modal/lightbox/flyouts/nav-menus).\n- [focus-trap](https://www.npmjs.com/package/focus-trap) - Trap focus within a DOM node.\n- [fullpage.js](https://www.npmjs.com/package/fullpage.js) - Create fullscreen scrolling websites.\n- [gsap](https://www.npmjs.com/package/gsap) - Professional-grade animation for the modern web.\n- [journalize](https://www.npmjs.com/package/journalize) - A collection of functions useful for making prose reader friendly.\n- [lodash](https://www.npmjs.com/package/lodash) - Various helper functions.\n- [slugify](https://www.npmjs.com/package/slugify) - Easily slug a string.\n- [@sveltejs/svelte-scroller](https://www.npmjs.com/package/@sveltejs/svelte-scroller) - Svelte-y scrollytelling\n- [svelte-select](https://www.npmjs.com/package/svelte-select) - A select/autocomplete component for Svelte apps. With support for grouping, filtering, async and more.\n- [swiper](https://www.npmjs.com/package/swiper) - Modern mobile touch slider with hardware accelerated transitions and amazing native behavior.\n\n### Deployment\n\n```bash\nnpm run build\n```\n\nIn the project root the command generates a directory called `build`. The built files have names without hashing thanks to [Rollup's config options](https://rollupjs.org/guide/en/#rolluprollup). You only need to embed once as the graphics are generated client-side.\n\nThe generated files will likely live in an S3 bucket or other storage site. Update the `base` url in `vite.config.js` to match the final URL of the files. A script to facilitate file uploading to S3 or another service can be easily written in the scripts folder.\n\n```js\nbase: mode === 'production' ? link : '/',\n```\n\nThe resulting `build/index.html` file is what can be embedded. It should look something like this, with a `\u003cfigure\u003e` element for each graphic, as well as `\u003cscript\u003e`s and `\u003clink\u003e`s to external files:\n\n```html\n\u003cscript type=\"module\" crossorigin src=\"https://www.site.com/path/to/index.js\"\u003e\u003c/script\u003e\n\u003clink rel=\"modulepreload\" href=\"https://www.site.com/path/to/vendor.js\"\u003e\n\u003clink rel=\"stylesheet\" href=\"https://www.site.com/path/to/vendor.css\"\u003e\n\u003clink rel=\"stylesheet\" href=\"https://www.site.com/path/to/index.css\"\u003e\n\n\u003cfigure data-cmsvelte=\"castle-img\"\u003e\u003c/figure\u003e\n\u003cfigure data-cmsvelte=\"bar-chart\"\u003e\u003c/figure\u003e\n\u003cfigure data-cmsvelte=\"ai2html\"\u003e\u003c/figure\u003e\n```\n\nScripts and styles should be embedded once anywhere in the CMS. The `\u003cfigure data-cmsvelte=\"\"\u003e` elements can be moved around as needed and do not need to live side-by-side. The `index.js` script will generate the graphics accordingly based on the `data-cmsvelte` attribute.\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsawyerclick%2Fcmsvelte","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsawyerclick%2Fcmsvelte","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsawyerclick%2Fcmsvelte/lists"}