{"id":13852719,"url":"https://github.com/charliewilco/downwrite","last_synced_at":"2025-03-16T19:32:07.195Z","repository":{"id":33708846,"uuid":"63579165","full_name":"charliewilco/downwrite","owner":"charliewilco","description":"✍️ Markdown writing application that's down right, neat.","archived":false,"fork":false,"pushed_at":"2023-04-23T11:16:25.000Z","size":11959,"stargazers_count":103,"open_issues_count":25,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-15T01:52:20.372Z","etag":null,"topics":["apollo","draft-js","graphql","nextjs","react"],"latest_commit_sha":null,"homepage":"https://beta.downwrite.us","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/charliewilco.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":".github/CONTRIBUTING.md","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}},"created_at":"2016-07-18T07:13:20.000Z","updated_at":"2024-03-11T11:59:00.000Z","dependencies_parsed_at":"2024-01-16T12:02:24.398Z","dependency_job_id":null,"html_url":"https://github.com/charliewilco/downwrite","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/charliewilco%2Fdownwrite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charliewilco%2Fdownwrite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charliewilco%2Fdownwrite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/charliewilco%2Fdownwrite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/charliewilco","download_url":"https://codeload.github.com/charliewilco/downwrite/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243826797,"owners_count":20354221,"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":["apollo","draft-js","graphql","nextjs","react"],"created_at":"2024-08-04T22:01:34.008Z","updated_at":"2025-03-16T19:32:06.749Z","avatar_url":"https://github.com/charliewilco.png","language":"TypeScript","readme":"# ![Downwrite](.github/images/downwrite-og.png)\n\n![Node CI](https://github.com/charliewilco/downwrite/workflows/Node%20CI/badge.svg)\n![E2E Testing](https://github.com/charliewilco/downwrite/workflows/E2E%20Testing/badge.svg)\n\n## About 🤔🦄🎉\n\n\u003e _A place to write._ ✍️\n\nSo the idea here was simple build a simple markdown writing application. Markdown is a huge deal and all the cool tools kept getting shut down and naively,I thought, _how hard can this really be_? 🤔📝📦\n\nSo I've had poorly designed iterations of this thing for every year, on the year as one of these services got shut down. When [Canvas](https://blog.usecanvas.com/) shut down this last year, I started to get a little more serious about this idea. 💡 ⚡🔭\n\nDuring planning out some of my quarterly goals at my last job I decided to go a little more full-stack with Node and start to really work through the process of building a microservice. Since I'm never really one to learning languages and frameworks in the abstract, I decided to take up Downwrite as an excuse to build those microservices. 📡💸🌎\n\n### Why Markdown 🧐🤨📋\n\nMarkdown is probably the most efficient and universal tool for conveying syntax, semantics and structure across platforms. ⬇️\n\nOriginally coined by [John Gruber (Daring Fireball)](https://daringfireball.net/projects/markdown/) it was originally conceived as a text to HTML and is the staple of static site generators, OSS as well as a fair amount of comment sections, notetaking applications or any documentation tool. 🛠\n\nThese shortcuts are almost as ubiquitous as `cmd + b` for bold or `cmd + i` for italics. ⌨️\n\n\u003e Bottomline: markdown is data. It is a method for describing semantics of data and is data itself.\n\n## Features ✨🔥🚀\n\nThis is meant to be a simple writing application with some key features:\n\n- Write wherever you are in markdown\n- Share what you've written if you want\n- Upload a markdown file from your machine\n- Export to a static markdown file for your blog, etc.\n\n## Setup 📲⏳⚙️\n\nThis project uses Node (v12.18.x), [TypeScript](https://www.typescriptlang.org/) and pnpm.\n\n```bash\nbrew cask install pnpm\npnpm install\n```\n\nPersonally use [`fnm`](https://github.com/Schniz/fnm) to manage my node versions.\n\n```bash\nfnm install\nfnm use\n```\n\n### Environment\n\nTo get started create an `.env` file in the root of your project with the following\n\n```env\nSECRET_KEY=\"SECRET SECRETS ARE NO FUN\"\nCURRENT_DB_ADDRESS=\"127.0.0.1:27017/downwrite\"\n```\n\n### Client ⚡️🦊\n\n![Logos for Related Projects](.github/images/Client-2020.png)\n\n#### Setup\n\nRun in your terminal from the root of the project.\n\n```bash\npnpm dev\n```\n\nOpen [`http://localhost:3000`](http://localhost:3000/) in your browser.\n\n#### UI 📝\n\nThis is the client-side of the application, it uses Next.js and is a pretty stock implementation of how Next handles routing to different views. 👨‍💻🤜🦑🤯\n\nDownwrite needs to server side rendered to make sharing an entry as easy as possible. Next.js' data-fetching API makes it the perfect candidate. So when the page calls `getServerSideProps()` it fetches the data directly from the database (DB creditentials aren't exposed to the client build at all because of the bundling features inside Next 😁) and for the initial render it has data available instead of a skeleton screen. 🤖☠️💀\n\nFor the Editor this project uses Draft.js and Draft.js Plugins. Markdown syntax is used inline and autogenerates the related rich text `_hello_` becomes \"_hello_\" as you type.💻⌨️🔏\n\nFor styles I just used the built-in CSS support in Next.js\n\n#### Serverless Functions 🌎✨\n\nTo update the data, this project calls endpoints at `/api/....` to enable this we're using Next'js [API Routes](https://nextjs.org/docs/api-routes/introduction). These are serverless functions so we don't need to keep a server or database connectioin running all the time, with serverless functions you're essentially calling the API on-demand.\n\nThis project also depends on MongoDB 🍍 for data persistence, you should see this [gist](https://gist.github.com/nrollr/9f523ae17ecdbb50311980503409aeb3) on how to setup MongoDB on your machine.\n\nTo authenticate we're using JWT to call the basic CRUD functions. Basically this is using a stateless auth model, more about that [here](https://auth0.com/blog/stateless-auth-for-stateful-minds/). 🔐\n\n#### Related Documentation 📚\n\n- [TypeScript](https://www.typescriptlang.org/)\n- [React](https://reactjs.org/)\n- [Next.js](https://nextjs.org/)\n- [Formik](https://formik.org/)\n- [Draft.js](https://draftjs.org/)\n- [Draft.js Plugins](https://www.draft-js-plugins.com/)\n- [Reach UI](https://reach.tech/)\n- [MDX](https://mdxjs.com/)\n- [MongoDB](https://docs.mongodb.com/manual/support/) \u0026 [Mongoose.js](http://mongoosejs.com)\n- [JWT](https://auth0.com/blog/hapijs-authentication-secure-your-api-with-json-web-tokens/)\n\n### Integration Testing 🌈🦁🐛\n\n![Logos for Related Projects](.github/images/Integration.png)\n\n```bash\npnpm test\n```\n\n#### Info 📝🧪\n\nShort hand: `page` is just a representation of whatever the headless browser, _Puppeteer_ has rendered at that given moment.\n\nUsing Puppeteer I write assertions like this:\n\n```js\ndescribe(\"Feature\", () =\u003e {\n\tit(\"does this thing\", async () =\u003e {\n\t\tawait page.waitForSelector(\"#selector\");\n\t\tawait page.click(\"#selector\");\n\t\tawait page.waitForSelector(\"#other-selector\");\n\t});\n});\n```\n\nThis approach accomplishes two things:\n\n- Ensures if an `await` statement errors or `catch()` the block will cause a failure\n- Makes the test sequential and simpler to write\n\n#### Related Documentation 📚\n\n- [Puppeteer](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md)\n- [Jest](https://jestjs.io/)\n- [_End-to-end Tests that Don’t Suck with Puppeteer_ from Trevor Miller](https://ropig.com/blog/end-end-tests-dont-suck-puppeteer/)\n- [_Write tests. Not too many. Mostly integration._ from Kent C. Dodds](https://blog.kentcdodds.com/write-tests-not-too-many-mostly-integration-5e8c7fff591c)\n\n### Workflow 👷‍♀️🚧\n\nWorking on this project it uses GitHub actions to run the tests and deploys using [`vercel`](https://vercel.com) for easy rollback and immutable deployments.\n\n## License ⚖️💣🛡⚔️\n\nMIT License\n\nCopyright (c) 2022 Charlie Peters\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcharliewilco%2Fdownwrite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcharliewilco%2Fdownwrite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcharliewilco%2Fdownwrite/lists"}