{"id":21890098,"url":"https://github.com/ejfox/sstory","last_synced_at":"2025-07-02T09:36:11.645Z","repository":{"id":3264390,"uuid":"4303298","full_name":"ejfox/sStory","owner":"ejfox","description":"A javascript library to help make full-browser-width magazine-style mini-sites.","archived":false,"fork":false,"pushed_at":"2014-05-11T05:28:31.000Z","size":5033,"stargazers_count":91,"open_issues_count":1,"forks_count":29,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-06-26T19:12:09.109Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://ejfox.github.com/sStory/","language":"CSS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ejfox.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2012-05-12T01:16:31.000Z","updated_at":"2024-01-21T22:23:21.000Z","dependencies_parsed_at":"2022-08-23T14:30:41.484Z","dependency_job_id":null,"html_url":"https://github.com/ejfox/sStory","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ejfox/sStory","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ejfox%2FsStory","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ejfox%2FsStory/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ejfox%2FsStory/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ejfox%2FsStory/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ejfox","download_url":"https://codeload.github.com/ejfox/sStory/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ejfox%2FsStory/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263112455,"owners_count":23415620,"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":[],"created_at":"2024-11-28T11:28:47.399Z","updated_at":"2025-07-02T09:36:11.609Z","avatar_url":"https://github.com/ejfox.png","language":"CSS","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sStory\nsStory is designed to make it easy to tell beautiful stories on the web with a variety of media. It will take care of the presentation and technical aspects of telling a story through the web so that creators can focus on the narrative and gathering great material.\n\nsStory is an open-source self-hosted solution so that creators, journalists, and newsrooms can publish their work online without trusting someone else's server or terms of service. It is also meant to be customized and extended, Pull Requests and ideas welcome!\n\n\n* Easily stitch together sections made of photos, videos, sounds, maps and more\n* Focused on beautiful presentation and interactions\n* Extendable, made to fit into pre-existing systems and CMS\n* Supports YouTube, Vimeo, SoundCloud, and more for embedding media\n* Your story's structure is stored in hand-editable JSON\n\n## Getting Started\n\n\n### Set up\n**index.html** in the main directory is an example of an HTML file with all of the dependencies. \n\nIf aren't including sStory into a pre-existing site or CMS, you can rename and modify **index.html** and skip to [creating the story_list](#create-your-story-list).\n\n#### Custom Installation\n\nYou will need to sStory itself (both JS and CSS), as well as *3rdparty.min.js* which contains all of the 3rd party JS files combined and minified. The maps also default to using [Stamen map tiles](http://maps.stamen.com/#watercolor/12/37.7706/-122.3782), which you will need to include if you will be using any map sections. \n\n```\n\u003cscript src=\"lib/js/3rdparty.min.js\" type=\"text/javascript\" charset=\"utf-8\"\u003e\u003c/script\u003e\n\u003cscript src=\"http://maps.stamen.com/js/tile.stamen.js?v1.2.4\" type=\"text/javascript\"\u003e\u003c/script\u003e  \n\u003cscript src=\"lib/js/sstory.js\" type=\"text/javascript\" charset=\"utf-8\"\u003e\u003c/script\u003e\n\u003clink rel=\"stylesheet\" href=\"lib/styles/style.css\" type=\"text/css\" media=\"screen\" title=\"sStory Styles\" charset=\"utf-8\"\u003e\n```\n\nYou will also need a DOM element with the id of **#content** which sStory will fill with the content of the story. \n```\n\u003cbody\u003e\n\u003cdiv id=\"#content\"\u003e\u003c/div\u003e\n\u003c/body\u003e\n```\n\n### Create your story list\nThe story_list is the heart of every sStory, and it is essentially an array of objects, one for each section. It is order-specific, with the first item appearing at the top of the page.\n\nOnce the document has loaded, simply create a new sStory and feed it the story_list array, and then render.\n\n```\n// Story list\nvar story_list = [\n      {\n        type: 'locationSinglePlace'\n        ,address: \"1600 Pennsylvania Ave NW  Washington, DC\"\n        ,caption: \"An address!\"\n      }\n      ,{\n        photoUrl: 'http://farm9.staticflickr.com/8315/8018537908_eb5ac81027_b.jpg'\n        ,type: 'photoBigText'\n        ,title: 'Making beautiful stories easy'\n      }\n]\n\nvar story = new sStory(story_list)\nstory.render()\n```\n\n![Here's what that example story looks like](https://github.com/ejfox/sStory/raw/tabula-rasa/documentation/basic_story.png)\n\nIf you'd like to have a header with navigation / the title of your article, include the following HTML. Replace the content of the `\u003ch1\u003e` and `\u003ch4\u003e` tags with your own title / subtitle. \n```\n\u003cnav id=\"header\"\u003e\n  \u003cdiv id=\"header-content\" class=\"show-front\"\u003e\n    \u003cdiv id=\"header-front\"\u003e\n      \u003ch1 id=\"title\"\u003eTitle of this story\u003c/h1\u003e\n      \u003ch4 id=\"subtitle\"\u003eSubtitle / Section title\u003c/h4\u003e\n    \u003c/div\u003e\n\n    \u003cul id=\"navigation\"\u003e\n    \u003c/ul\u003e\n\n    \u003cdiv id=\"header-bottom\"\u003e\u003cdiv id=\"progress\" style=\"width: 0%;\"\u003e\u0026nbsp;\u003c/div\u003e\u003c/div\u003e\n  \u003c/div\u003e\n\u003c/nav\u003e\n```\n\n## Section Types\nAll sections, even if they do not require it, can accept a 'title' parameter which will be displayed in the navigation menu. \n\n### Text\n\nText sections accept HTML and display it in an easy-to-read line width. Currently text sections are very basic, but will soon include the ability for asides with a variety of media.\n```\n{\n  type: 'text'\n  ,html: '\u003ch2\u003eScraping your own data\u003c/h2\u003e\u003cp\u003eThis morning as I was browsing my Twitter feed, \u003ca href=\"http://www.people-press.org/obama-romney-voter-preferences/\"\u003eI found Pew had released an interesting set of data\u003c/a\u003e. Of course my first instinct is to visualize it. However, their data was locked in a table on their website. It wasn’t available for download as a CSV, or through a JSON API. \u003cstrong\u003eOh well, let’s make our own.\u003c/strong\u003e\u003c/p\u003e'\n}\n```\n\n### Photo\nPhoto sections stretch to fill the entire browser window (images will be cropped and display differently on devices with different aspect ratios). They **must have** a photo URL. They can **optionally** have a title or caption.\n\n**photoBigText:** Which is for photos with no title, or photos with just a title.\n```\n{\n  type: 'photoBigText'\n  ,photoUrl: 'http://farm9.staticflickr.com/8315/8018537908_eb5ac81027_b.jpg'\n  ,title: 'Making beautiful stories easy'\n}\n```\n\n**photoCaption:** Which is for photos with a caption, or with a caption and a title.\n```\n{\n  type: 'photoCaption'\n  ,photoUrl: 'http://farm9.staticflickr.com/8315/8018537908_eb5ac81027_b.jpg'\n  ,title: 'Making beautiful stories easy'\n  ,caption: '\u003ch3\u003eHello world!\u003c/h3\u003e\u003cp\u003eLorem ipsum \u003cem\u003edolor sit\u003c/em\u003e amet. Include styled \u003cspan style=\"color: red\"\u003eHTML\u003c/span\u003e!'\n\n}\n```\n\n**photoMulti:** is for including multiple photos in a single section, and doesn't support captions or titles.\n```\n{\n  type: 'photoMulti'\n  ,photoUrlArray: ['http://37.media.tumblr.com/76cd2f0e146ac4d6251bd9ff28eb8307/tumblr_ms91cgSwmX1qcn8pro1_1280.jpg', 'http://24.media.tumblr.com/9a5c41e468022c91dfd201053d1a099b/tumblr_ms91cgSwmX1qcn8pro2_1280.jpg', 'http://24.media.tumblr.com/5aeb959fd9c416f18e80d27b84384f1b/tumblr_ms91cgSwmX1qcn8pro3_1280.jpg']\n}\n```    \n\n### Video\nYou can add video sections with embedded videos from YouTube or Vimeo. You will give the entire embed code to sStory.\n\n**videoYoutube:** Add videos from YouTube by using their embed code. You can find it in the _share_ tab beneath each video by clicking the _embed_ button. You don't need to change any of the options. You will be given some code for an iFrame embed.\n\n```\n{\n  type: 'videoYoutube'\n  ,embedCode: '\u003ciframe width=\"420\" height=\"315\" src=\"//www.youtube.com/embed/dQw4w9WgXcQ?rel=0\" frameborder=\"0\" allowfullscreen\u003e\u003c/iframe\u003e'\n}\n```\n\n**videoVimeo:** Vimeo videos can be added the same way YouTube videos are added. Simply add the embed code to sStory. You can find Vimeo's embed code by clicking on the _share_ button that appears in the top-right of videos.\n\n```\n{\n  type: 'videoVimeo'\n  ,embedCode: '\u003ciframe src=\"http://player.vimeo.com/video/35912908?badge=0\" width=\"500\" height=\"281\" frameborder=\"0\" webkitAllowFullScreen mozallowfullscreen allowFullScreen\u003e\u003c/iframe\u003e \u003cp\u003e\u003ca href=\"http://vimeo.com/35912908\"\u003eFACETURE\u003c/a\u003e from \u003ca href=\"http://vimeo.com/user9669590\"\u003ePhil Cuttance\u003c/a\u003e on \u003ca href=\"https://vimeo.com\"\u003eVimeo\u003c/a\u003e.\u003c/p\u003e'\n}\n```\n\n### Sound\n**soundSoundcloud:** Audio from soundcloud can be embedded as well. You can find the embed code by clicking on the _share_ button in the bottom of each Soundcloud player. It is the iframe code labeled _Widget Code_.\n\n```\n{\n  type: 'soundSoundcloud'\n  ,embedCode: '\u003ciframe width=\"100%\" height=\"166\" scrolling=\"no\" frameborder=\"no\" src=\"https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F99067369\"\u003e\u003c/iframe\u003e'\n}\n```\n\n### Location\n**locationSinglePlace:** A single location with an address and a caption. A leaflet map is generated with a marker and a popup with the provided caption. An optional photoUrl can be provided to add an image to the popup.\n```\n{\n  type: 'locationSinglePlace'\n  ,address: \"1600 Pennsylvania Ave NW  Washington, DC\"\n  ,caption: \"An address!\"\n}\n```\n\n### Code\n\n**codeTributary:** Embed a live Tributary example.\n\n```\n{\n  type: 'codeTributary'\n  ,url: 'http://tributary.io/tributary/2958568/'\n}\n```\n\n### Timeline\n**timelineVerite:** Include a [Timeline JS](http://timeline.verite.co/) timeline embed, which you can find at step 4 of [TimelineJS walkthrough here](http://timeline.knightlab.com/).\n```\n{\n  type: 'timelineVerite'\n  ,embedCode: \"\u003ciframe src='http://cdn.knightlab.com/libs/timeline/latest/embed/index.html?source=0ApAkxBfw1JT4dFVxOEk0aGRxbk9URE9yeDJKMXNIS3c\u0026font=Bevan-PotanoSans\u0026maptype=toner\u0026lang=en\u0026start_at_slide=1\u0026height=650' width='100%' height='650' frameborder='0'\u003e\u003c/iframe\u003e\"\n}\n```\n\n\n## FAQ\n\n#### How big is it?\nsStory itself is 34kb uncompressed. It's dependencies are around 388kb, but include things like jQuery and Underscore which you may already be serving. \n\n#### How do I adjust the size of photos?\nShort answer: you can't. Photos will stretch to fill the screen, and if the aspect ratio of the user's screen is different than the photo, the sides of the photo may be cropped out. Because of this, only content in the center of the photo can be guaranteed to be seen on all screens. ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fejfox%2Fsstory","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fejfox%2Fsstory","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fejfox%2Fsstory/lists"}