{"id":20779628,"url":"https://github.com/smartlogic/stein_example","last_synced_at":"2025-10-10T20:33:58.306Z","repository":{"id":42961192,"uuid":"227906739","full_name":"smartlogic/stein_example","owner":"smartlogic","description":"An example application that uses Stein for common functions of a web application","archived":false,"fork":false,"pushed_at":"2023-07-19T02:14:44.000Z","size":859,"stargazers_count":7,"open_issues_count":6,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-08-09T17:56:09.761Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Elixir","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/smartlogic.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-12-13T19:16:49.000Z","updated_at":"2022-04-26T04:50:35.000Z","dependencies_parsed_at":"2025-04-30T19:44:18.374Z","dependency_job_id":"c68d3203-de02-4808-92c2-2f0f99caf800","html_url":"https://github.com/smartlogic/stein_example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/smartlogic/stein_example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartlogic%2Fstein_example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartlogic%2Fstein_example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartlogic%2Fstein_example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartlogic%2Fstein_example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smartlogic","download_url":"https://codeload.github.com/smartlogic/stein_example/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartlogic%2Fstein_example/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270235436,"owners_count":24550183,"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","status":"online","status_checked_at":"2025-08-13T02:00:09.904Z","response_time":66,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2024-11-17T13:28:59.276Z","updated_at":"2025-10-10T20:33:53.286Z","avatar_url":"https://github.com/smartlogic.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SteinExample\n\nThis is an example Phoenix application that uses [Stein](https://github.com/smartlogic/stein) to it's fullest. See how to handle common user functionality with Stein, such as auth, email verification, password resets, uploading, and more.\n\nYou can also clone this repo as a starting point for a new project to get going quickly.\n\n## Setup\n\nInstall PostgreSQL through your package manager of choice, or if you're on MacOS you can use [Postgres.app](https://postgresapp.com/). Make sure to have **PostgreSQL 12** or above.\n\n### With ASDF\n\nInstall Elixir, Erlang, and NodeJS through [asdf](https://asdf-vm.com/#/) using the versions supplied in `.tool-versions`. Once you have asdf, you can install them all with `asdf install` from the root of the project.\n\n```bash\n# Install Erlang/Elixir/NodeJS\nasdf install\n# Install yarn if required\nnpm install -g yarn\n\nmix deps.get\nmix ecto.setup\n(cd assets \u0026\u0026 yarn install \u0026\u0026 yarn build)\niex -S mix phx.server\n```\n\nNow you can visit [`localhost:4000`](http://localhost:4000) from your browser. See `priv/repo/seeds.exs` for seeded accounts.\n\n### With Nix\n\nInstall [the nix package manager](https://nixos.org/download.html#nix-install-macos) by following their multi-user installer. Once nix is installed, setup [direnv](https://direnv.net/) by hooking into your shell.\n\n```bash\nnix-env -f '\u003cnixpkgs\u003e' -iA direnv\necho 'eval \"$(direnv hook zsh)\"' \u003e\u003e ~/.zshrc\n```\n\nOnce direnv is installed and your shell is restarted, clone the project and `cd` into it. You should see direnv warn about an untrusted `.envrc` file. Allow the file and finish installing dependencies and setting up the application.\n\n```bash\ndirenv allow\n\nmix deps.get\nmix ecto.reset\n(cd assets \u0026\u0026 yarn install \u0026\u0026 yarn build)\niex -S mix phx.server\n```\n\nNow you can visit [`localhost:4000`](http://localhost:4000) from your browser. See `priv/repo/seeds.exs` for seeded accounts.\n\n## Testing\n\nIn order to verify our application, we have a series of tests that run in CI. Below is a list of them individually.\n\n```bash\nmix format --check-formatted\nmix compile --force --warnings-as-errors\nmix credo\nmix test\n(cd assets \u0026\u0026 yarn lint:ci)\n(cd assets \u0026\u0026 yarn lint:style:ci)\n```\n\nAlternatively, you can run them all together with the verify script.\n\n```bash\n./verify.sh\n```\n\n## Using as a template\n\n**Note: You must follow through with the admin panel section**\n\n```bash\ngit grep -l SteinExample | xargs sed -i 's/SteinExample/MyApp/g'\ngit grep -l stein_example | xargs sed -i 's/stein_example/my_app/g'\ngit mv lib/{stein_example,my_app}\ngit mv lib/{stein_example,my_app}.ex\ngit mv test/{stein_example,my_app}\nrm -rf .git\ngit init .\n```\n\n**On a Mac**\nThe first two lines of above will likely need to be changed to the following to work:\n```bash\ngit grep -l SteinExample | xargs sed -i '' 's/SteinExample/MyApp/g'\ngit grep -l stein_example | xargs sed -i '' 's/stein_example/my_app/g'\n```\n\n### Admin Panel\n\nThe app ships with the start of an admin panel. Something that you **must do** after getting it set up is add permissioning to the panel. Every signed in user can access the panel from first clone. This is on purpose because there are many styles of roles/permissions and each app will have their own.\n\n### Deployment\n\nThis application is set up to deploy heroku and via ansible to a VPS. When initially templating the application, you can clear out the deployment option that we're not using.\n\n#### Ansible\n\nAnsible deployment is only configured for Vagrant deployment.\n\nIf we're not using ansible, delete the following:\n\n```bash\nrm -r ./deploy ./ansible.cfg ./Vagrantfile ./release.sh\n```\n\nIf we're using ansible, run the following to template for the new application:\n\n```bash\ngit mv deploy/files/stein_example.local.env deploy/files/my_app.local.env\ngit mv deploy/files/stein_example.service deploy/files/my_app.service\n```\n\nUpdate the `git_repo` variable in `./bin/remote`\n\n#### Heroku\n\nIf we're not using heroku, delete the following:\n\n```bash\nrm ./phoenix_static_buildpack.config ./elixir_buildpack.config\n```\n\n## Deployment\n\n### Ansible Deployment\n\nInstall [Vagrant](https://www.vagrantup.com/), [VirtualBox](https://www.virtualbox.org/), and [Ansible](https://www.ansible.com/).\n\n```bash\nansible-galaxy install -r deploy/requirements.yml\nvagrant up\nansible-playbook -l local deploy/setup.yml\nansible-playbook -l local deploy/deploy.yml\n```\n\nThe `setup.yml` playbook installs and configures common components (ssh, ntp, firewall, traefik, postgresql) and the `deploy` user.\n\nThe `deploy.yml` playbook generates a local release, copies it over to the application server, migrates, and restarts the application. This is in a similar setup to capistrano with release folders.\n\nIn order to connect to a running service, connect via the `remote.sh` script:\n\n```bash\n./bin/remote local iex\n```\n\nIf you want to run a release task manually, ssh in as `deploy`:\n\n```bash\nexport $(cat /etc/stein_example.env | xargs)\ncd apps/stein_example/current\n./bin/stein_example eval \"SteinExample.ReleaseTasks.Migrate.run()\"\n```\n\nTo seed on staging:\n\n```bash\nexport $(cat /etc/stein_example.env | xargs)\ncd apps/stein_example/current\n./bin/stein_example eval \"SteinExample.ReleaseTasks.Seeds.run()\"\n```\n\n#### Remote Script\n\nTo help facilitate remote debugging, we have a script to start a remote IEx or psql session.\n\n```bash\n# To start a bash session\n./bin/remote production bash\n\n# To start an IEx session\n./bin/remote production iex\n\n# To start a psql session\n./bin/remote production psql\n```\n\nSee `./bin/remote` for more of what it can do, as that help is more up to date.\n\n### Docker locally\n\nDocker is set up as a replication of production. This generates an erlang release and is not intended for development purposes.\n\n```bash\ndocker-compose pull\ndocker-compose build\ndocker-compose up -d postgres\ndocker-compose run --rm app eval \"SteinExample.ReleaseTasks.Migrate.run()\"\ndocker-compose run --rm app eval \"SteinExample.ReleaseTasks.Seeds.run()\"\ndocker-compose up app\n```\n\nYou now can view `http://localhost:4000` and access the application.\n\n### Heroku\n\nBuildpacks required:\n\n- https://github.com/HashNuke/heroku-buildpack-elixir.git\n- https://github.com/gjaldon/heroku-buildpack-phoenix-static.git\n- https://github.com/oestrich/heroku-buildpack-elixir-mix-release.git\n\nTo migrate on heroku:\n\n```bash\nheroku run 'stein_example eval \"SteinExample.ReleaseTasks.Migrate.run()\"'\n```\n\n## Metrics\n\nA metric server will start on `http://localhost:4021/metrics`, set up for [Prometheus](https://prometheus.io/) scraping.\n\nIf deploying via Heroku, you should remove the metric server config and host it via the `PromEx.Plug` through `Web.Endpoint`.\n\nIf deploying via ansible, then port `4021` should be accessible via our metrics server.\n\n### Dashboards\n\nBy default PromEx is not configured to upload dashboards to Grafana. For local development or the first time setting up dashboards on our metrics server, you can use the following ENV to confiugre PromEx to upload dashboards.\n\n```bash\nGRAFANA_API_TOKEN=api-token-that-is-an-editor\nGRAFANA_URL=http://localhost:3000\nGRAFANA_UPLOAD_DASHBOARDS=true\nGRAFANA_DATASOURCE_ID=datasource-id-for-prometheus\n```\n\nAfterwards on boot PromEx will upload the configured dashboards to the Grafana server.\n\n### Prometheus Job\n\nTo configure our Prometheus to scrape the server, setup a new file config similar to below. Make sure to update `client`, `product`, and `datacenter` with the appropriate label values.\n\n```json\n[\n  {\n    \"targets\" : [\n      \"ip:4021\"\n    ],\n    \"labels\" : {\n      \"job\" : \"app\",\n      \"client\" : \"product\",\n      \"datacenter\" : \"aws-us-east\",\n      \"product\" : \"product\",\n      \"environment\" : \"staging\"\n    }\n  },\n  {\n    \"targets\" : [\n      \"ip:4021\",\n      \"ip:4021\"\n    ],\n    \"labels\" : {\n      \"job\" : \"app\",\n      \"client\" : \"client\",\n      \"datacenter\" : \"aws-us-east\",\n      \"product\" : \"product\",\n      \"environment\" : \"production\"\n    }\n  }\n]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmartlogic%2Fstein_example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmartlogic%2Fstein_example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmartlogic%2Fstein_example/lists"}