{"id":13832416,"url":"https://github.com/wincent/masochist","last_synced_at":"2025-03-16T16:32:24.198Z","repository":{"id":2643984,"uuid":"43113651","full_name":"wincent/masochist","owner":"wincent","description":"⛓ Website infrastructure for over-engineers","archived":false,"fork":false,"pushed_at":"2024-04-10T07:43:46.000Z","size":742734,"stargazers_count":79,"open_issues_count":23,"forks_count":26,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-04-10T08:39:26.799Z","etag":null,"topics":["graphql","markdown","react","relay","vim"],"latest_commit_sha":null,"homepage":"","language":"Hack","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/wincent.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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}},"created_at":"2015-09-25T06:31:41.000Z","updated_at":"2024-04-14T21:39:07.083Z","dependencies_parsed_at":"2024-04-14T21:49:10.930Z","dependency_job_id":null,"html_url":"https://github.com/wincent/masochist","commit_stats":{"total_commits":1007,"total_committers":2,"mean_commits":503.5,"dds":0.0009930486593843213,"last_synced_commit":"2872a7b46039c2ef708e47f214e94e5167a341b4"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wincent%2Fmasochist","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wincent%2Fmasochist/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wincent%2Fmasochist/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wincent%2Fmasochist/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wincent","download_url":"https://codeload.github.com/wincent/masochist/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221666150,"owners_count":16860376,"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":["graphql","markdown","react","relay","vim"],"created_at":"2024-08-04T10:02:02.541Z","updated_at":"2024-10-27T10:57:24.860Z","avatar_url":"https://github.com/wincent.png","language":"Hack","funding_links":[],"categories":["Hack","Rust"],"sub_categories":[],"readme":"# What\n\nThis repo contains the source code and content for my website at [wincent.dev].\n\nContent is authored in plain-text-friendly markup formats like [Markdown] and\nserved using a dynamic stack (described below). New code can be deployed and\ncontent added or updated via `git push`.\n\n## Stack\n\n- [React]: Declarative, component-oriented view layer.\n- [Relay]: Declarative data-management.\n- [GraphQL]: Hierarchical data querying language, type system and server.\n- [Git]: Main content storage.\n- [Redis]: Indexing and caching.\n- [memcached]: Ephemeral caching.\n\nSupporting tools and technologies:\n\n- [Markdown]: Preferred content markup.\n- [Neovim], with help from [Corpus]: Content editing.\n- [Marked 2]: Local content previewing.\n\n## Questions\n\n### Why not use a static site generator?\n\nA static site generator would very much be the right tool for this job, however, building the site on a custom [React]/[Relay]/[GraphQL] stack was much more fun, so I did that instead.\n\n### Why the name \"Masochist\"?\n\nPlease see the introductory blog post, \"[Introducing Masochist](https://github.com/wincent/masochist/blob/content/content/blog/masochist.md)\".\n\n# Development\n\n## Quickstart\n\n### Prerequisites\n\n```\nbrew install git memcached redis\n```\n\n### Webpack-based hot-loading workflow\n\n```\ngit clone https://github.com/wincent/masochist.git\ncd masochist\nyarn\nyarn update-schema\nyarn update-indices # Whenever content changes.\nyarn start\n```\n\n### Running in production-like environment\n\n```\nyarn run build # Builds files under `dist/`.\nyarn start-prod\n```\n\n### Running in production\n\n```\nexport NODE_ENV=production\nyarn\nyarn build\nnode dist/bin/updateIndices.js # Whenever content changes.\nnode dist/server/main.js\n```\n\n### Configuration\n\nIn `__DEV__`, Masochist will look for content in the current repo (ie. `.`).\n\nIn production, it expects to find a content repo at `/srv/masochist/content`.\n\nIn `__DEV__`, you can override this with `npm config set`. For example, in my local development environment, I have the Masochist Git repo checked out in one folder, and a second copy of it with the `content` branch checked out within it (using `git-worktree`) at `./content` (see below for more details on this set-up). I can override the `__DEV__` default of `.` with:\n\n```\n# Use npm, not yarn, for this:\nnpm config set masochist:content-repo './content'\n```\n\n### Deployment cheatsheet\n\nYou could do this in any number of ways but the way I'm doing it is using two local repositories as follows:\n\n#### Local \"masochist\" repository\n\n##### Structure\n\n* `main` branch checked out.\n* `origin` remote pointing at git.wincent.dev.\n* `github` remote pointing at [GitHub](https://github.com/wincent/masochist).\n* `masochist` remote set up to do Heroku-style deploy-on-push, pointing at an Amazon EC2 instance configured using Ansible.\n* `content` remote set up to do a Heroku-style update-on-push for content changes, pointing at the corresponding repository on EC2.\n\n##### Commands\n\n```\n$ git push masochist main # Deploy app (after initial provisioning).\n$ git push masochist # Subsequent deployments.\n$ git push origin # Propagate code, but no deploy.\n$ git push # Shorthand for `git push origin`.\n$ git push github # If you can't be bothered waiting for it to auto-replicate.\n```\n\n#### Local \"content\" worktree\n\n##### Structure\n\n* `content` branch checked out.\n* `content` remote configured to do Heroku-style push-to-publish.\n* `origin` remote pointing at git.wincent.dev.\n* `github` remote pointing at [GitHub](https://github.com/wincent/masochist).\n\n##### Commands\n\n```\n$ git push content content # First push after initial provisioning.\n$ git push content # Subsequent pushes.\n$ git config branch.content.merge refs/heads/content # For laziness.\n$ git push # Simple.\n```\n\n##### Rollback to a prior rev `$HASH`\n\n```\n$ git push masochist +$HASH:main\n```\n\nOr just switch symlinks and `sudo monit restart masochist`.\n\n#### Force a deploy without actual code changes\n\n```\n$ git commit -m Deploy --allow-empty\n$ git push masochist\n```\n\n[Corpus]: https://github.com/wincent/corpus\n[Git]: https://git-scm.com/\n[GraphQL]: http://graphql.org/\n[Markdown]: https://en.wikipedia.org/wiki/Markdown\n[Marked 2]: http://marked2app.com/\n[memcached]: http://memcached.org/\n[React]: http://facebook.github.io/react/\n[Redis]: http://redis.io/\n[Relay]: http://facebook.github.io/relay/\n[Neovim]: https://github.com/neovim/neovim\n[wincent.dev]: https://wincent.dev/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwincent%2Fmasochist","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwincent%2Fmasochist","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwincent%2Fmasochist/lists"}