{"id":26714330,"url":"https://github.com/kstrassheim/ultimate-web-stack","last_synced_at":"2026-04-16T12:37:44.176Z","repository":{"id":284511410,"uuid":"955158073","full_name":"kstrassheim/ultimate-web-stack","owner":"kstrassheim","description":"A webstack which has all testing implemented but still provides a white code canvas for your own ideas","archived":false,"fork":false,"pushed_at":"2025-03-26T09:23:01.000Z","size":3086,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-26T09:32:29.887Z","etag":null,"topics":["azure","fastapi","react","testcafe","vite-react"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kstrassheim.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}},"created_at":"2025-03-26T07:43:07.000Z","updated_at":"2025-03-26T09:25:26.000Z","dependencies_parsed_at":"2025-03-26T09:43:49.479Z","dependency_job_id":null,"html_url":"https://github.com/kstrassheim/ultimate-web-stack","commit_stats":null,"previous_names":["kstrassheim/ultimate-web-stack"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kstrassheim%2Fultimate-web-stack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kstrassheim%2Fultimate-web-stack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kstrassheim%2Fultimate-web-stack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kstrassheim%2Fultimate-web-stack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kstrassheim","download_url":"https://codeload.github.com/kstrassheim/ultimate-web-stack/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245850358,"owners_count":20682647,"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":["azure","fastapi","react","testcafe","vite-react"],"created_at":"2025-03-27T13:19:18.714Z","updated_at":"2026-04-16T12:37:44.164Z","avatar_url":"https://github.com/kstrassheim.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ultimate Web Stack\nThis project is based on Python (FastAPI) and gives the users a blank canvas in Python to publish their solutions within a website and in an acceptable technical framework to go into production with entra id users while avoiding producing legacy code. This concretely means the following features: Entra ID role-based authentication, Azure logging, e2e tests with mockup, unit tests (Jest, PyTest), authenticated RealTime WebSocket connections and many more features. The whole stack auto-installs via terraform and derives its settings into the frontend and backend. You just have to adjust the app name.\n\n## Features\nIn the following is a description of the provided features. **(please leave a star if you like this project)**\n- Terraform __auto__ installation and setup\n- Entra ID Authentication with __auto__ installation and setup **(You don't have to set up anything on frontend and backend)**\n- Azure Application Insight logging with __auto__ installation and setup\n- Test Driven Development Setup\n    - E2E Testing (Cypress) + Coverage\n    - Frontend Unit Testing (Jest) + Coverage \n    - Backend Unit Testing (PyTest) + Coverage\n    - Mockout of Entra ID Token Authentication to Passthrough during development and testing (Role Authentication stays)\n- Real Time Web Socket Connections with Token and Role Authentication\n- Responsive Design and PWA support out of the box\n- Logo flipping (Different Logo on dev, test, prod) \n- Running on Free Plan F1 of Azure App Service to avoid any unnecessary costs\n\n## Prerequisites\nIn the following is a guide on how to set up the prerequisites for this project.\n\n### Installation on Windows\nThis is how to install the prerequisites on Windows.\n1. Install Chocolatey Installer https://chocolatey.org/. Open PowerShell Console in Admin Mode\n```powershell\nSet-ExecutionPolicy Bypass -Scope Process -Force;\n[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12;\nInvoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'));\n```\n2. Install terraform with chocolatey and test if it was installed correctly that the command is available in root\n```bash\nchoco install terraform\nterraform -v\n```\n3. (Optional) Alternatively install OpenTofu as Alternative to Terraform (Set EXE=tofu env variable)\n```powershell\nInvoke-WebRequest -outfile \"install-opentofu.ps1\" -uri \"https://get.opentofu.org/install-opentofu.ps1\"\n\u0026 .\\install-opentofu.ps1 -installMethod standalone -skipVerify\n```\n4. Download and install Python https://www.python.org/downloads/ \n5. Download and install Node.js https://nodejs.org\n\n### Installation on Linux-WSL\n```bash\n# Update package lists\nsudo apt-get update\n\n# Install system dependencies\nsudo apt-get install -y libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2-dev libxtst6 xauth xvfb fonts-liberation libappindicator3-1 libatk-bridge2.0-0 libatk1.0-0 libcups2 libdbus-1-3 libnspr4 libu2f-udev libvulkan1 wget gnupg curl python3 python3-pip python3-venv python3-pytest nodejs npm\n\n# Install Google Chrome\nwget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -\nsudo sh -c 'echo \"deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main\" \u003e\u003e /etc/apt/sources.list.d/google-chrome.list'\nsudo apt-get update\nsudo apt-get install -y google-chrome-stable\n\n# Install Microsoft Edge\ncurl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor \u003e microsoft.gpg\nsudo install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/\nsudo sh -c 'echo \"deb [arch=amd64] https://packages.microsoft.com/repos/edge stable main\" \u003e /etc/apt/sources.list.d/microsoft-edge.list'\nsudo rm microsoft.gpg\nsudo apt-get update\nsudo apt-get install -y microsoft-edge-stable\n```\n\n### Initialization\nIn the following is a guide to initialize the project to be your custom project.\n\n#### Quick Init (Mock run without Terraform)\nFor a quick init start of the application just run\n```bash\n./initq.sh\n```\non Linux or \n```powershell\n./initq.ps1\n```\non Windows.\nIt will set up the web applications to be runnable in __Mocked__ Debug mode without touching terraform.\n\n### Terraform Local Setup\nYou have to set the following variables in the terraform var and tfvar files to attach the terraform installation to your project.\n\n#### terraform_vars.tf\nThe following variable is very important to set because it's the name of the application and many other resources throughout the whole application are dependent on it.\n- __app_name__ - the short name of the application - many names in terraform are derived from this.\n\n#### Other variables (Optional)\nThe app is fully capable of running in Azure Free Plan but if you require more performance you can change these variables whether in var file (Default or in the specific environment file).\n- web_plan_sku - \"F1\", \"B1\" ... will define the web plans for azure app services. For more information about the performance and costs, you can check this page https://azure.microsoft.com/en-us/pricing/details/app-service/windows/\n- web_instances_count - The compute instances used for the plan. Per default it's 1.\n\nYou should not touch the env variable unless you really want to change the naming everywhere.\n\n#### Terraform deployment\nWhen you have set up everything, then __terraform will handle the whole deployment of the resources and the web application__. \n\n### Init Web Project\nWhen you have set up terraform correctly, run the command to set up the web applications ready to run. Please note that you have to log on to Azure and select the correct subscription to make terraform run.\n```bash\naz login\n./init.sh\n```\non Linux or \n```powershell\naz login\n./init.ps1\n```\non Windows.\nThis will first run terraform to adjust or install the Azure resources like the app registration and further will copy the terraform output to backend and frontend where its settings will be applied to adjust the authentication.\n\n### VSCode setup, run and debugging\nIn the following is the VSCode setup to run and debug the application.\nYou need the following plugins to be installed in VS Code to enable Python debugging. Node.js runs natively as VSCode is designed for it.\n- Python\n- Python Debugger\n\nWhen you open the Run and Debug section of VSCode, you will see all separate Frontend (Vite) and Backend (FastAPI) runners which come separately also in a Mock version. The Mock versions switch the Entra ID Authentication to a pass-through mode with Sample users. You have to click on Login and it will auto-login with the first user. By clicking on \"Change User\" it will automatically select the next user.\n\n#### Full Stack runs\nThe full stack runs will start the whole page frontend and backend (whether in Mock or normal mode) plus Chrome in Debug mode. You can directly set breakpoints in backend as well as frontend to analyze the behavior or identify bugs on your page.\n\n#### Attach to Chrome\nThis helps you when you do TDD with Cypress e2e testing. After you start Cypress, you can attach to the browser to set breakpoints in the frontend. \n\n#### Jest Current Test\nThis is a special debugger where you can debug the currently opened Jest test as well as the referenced js and jsx files.\n\n### Test Runs\nHere we will regard how to start the test runs locally.\n\n#### Backend (PyTest)\nYou can start all test runs by calling. You have to be in the ./backend folder.\n```bash\npytest -v\n```\nor if you want to run a specific test file\n```bash\npytest -v [filepath]\n```\nto run the code coverage check you can call\n```bash\npytest --cov\n```\nfor a detailed view of the backend coverage \n```bash\npytest --cov --cov-report=html\n```\nafterward you can open index.html from the root project path to investigate the coverage in detail through the generated index.html page.\n\n#### Frontend (Jest)\nYou can start all Jest tests by\n```bash\nnpm t\n```\nor if you want to run a specific test file, use the Jest Current File debugger.\nYou can also call.\n```bash\nnpm run test:preview\n```\nto use a preview run this before starting Jest tests. This will open up a webpage where you can see the current state of the Jest test.\nYou have to call global.debug() from your test to update this window if you want a specific state. Also, since this is buggy sometimes you have to refresh the page yourself most of the time. \n\nTo perform a coverage check for Jest, you can run the following command\n```bash\nnpm run test:coverage\n```\nPlease note that it will only display coverage errors in the console when the coverage check fails.\nThe detailed coverage report can be found under index.html.\n\n#### E2E Cypress \nTo run the Cypress testing, you have multiple options. \nFor just opening the Cypress suite where you can manually select the tests to run, just run\n```bash\nnpm run test:e2e\n```\nFor running the tests __automatically__ on the console __without a view__, run\n```bash\nnpm run test:e2e:headless\n```\nIf you want to run automatically, just run. It will pop up a window where you can see how the page is tested. It will close after finishing the tests.\n```bash\nnpm run test:e2e:run\n```\nFor checking the coverage, use the following commands\n```bash\nnpm run test:e2e:coverage\nnpm run coverage:report:no-check\nnpm run check-coverage || true\n```\nThe coverage output is the same folder as Jest, just this report remains in the root of it `frontend/coverage/index.html`. You can see there in detail which lines are affected by it and which are not.\n\n#### Adjust coverage\nTo adjust the coverage, you have to edit the following files:\n- Backend pyproject.toml under Line 14 `fail_under = 80` (just one setting here)\n- Frontend `frontend/jest.config.js` Line 44\n  ```javascript\n      // Optional: Set coverage thresholds to make tests fail if coverage is too low\n      coverageThreshold: {\n        global: {\n          statements: 80,\n          branches: 70,\n          functions: 80,\n          lines: 80\n        },\n  ```\n- End 2 End Cypress / nyc .nycrc.json Line 7\n  ```javascript \n  {\n    \"statements\": 80,\n    \"branches\": 65,\n    \"functions\": 80,\n    \"lines\": 80,\n  }\n  ```\n\n#### Adjust Test Users\nThe test users with names are set up in accounts.js. You can change the existing users or add some new. Especially when you set up custom roles in your application, you would need to adjust that.\nJust be careful to keep the same structure.\n```javascript\nconst okabe = {\n  username: \"okabe.rintaro@futuregadgetlab.org\",\n  name: \"Rintaro Okabe\",\n  localAccountId: \"mad-scientist-id\",\n  idTokenClaims: {\n    roles: [\"Admin\"],\n    oid: \"mad-scientist-id\",\n    preferred_username: \"hououin.kyouma@futuregadgetlab.org\",\n    nickname: \"Hououin Kyouma\"\n  },\n};\n```\n\n### Pipeline Setup\nThe pipeline is preconfigured on the following setup:\n- On Pull Request\n  - Check Backend-Unit-Tests, Frontend-Unit-Tests and E2E tests in Parallel\n  - Check coverage within those tests __they will fail when coverage is not reached__\n  - Output coverage reports as artifacts\n- On Merge Main\n  - Deploy to development\n- On Tag \n  - Deploy to test\n- Manually (After Tag)\n  - Deploy to prod\n\nIf you want to disable the coverage fails, you have to adjust it in the files like described above.\n\n## Azure Setup\nCreate an empty resource group and make sure that you are at least Contributor of it.\n1. Go to your Project's (Env) Resource Group click on Create and Create a User assigned Managed Identity. There is no special setup on this point. Just create it.\n2. Add the Managed Identity as Contributor to the Resource Group to enable it deploying resources\n3. Assign the Managed Identity as Application Application Admin (Application Developer not worked out) to enable it creating application. This can be tricky a bit as you sometimes cannot assign it via Menu because it only shows users and Applications for that you can \n  - Open the Managed Identity and on Overview page get its __ObjectId__ (not ClientId)\n  - Open Azure CLI and type \n      ```powershell\n        Get-AzureADDirectoryRole\n      ```\n  - If it is in the list then get its ObjectId (of \"Application Administrator\" role) if not you have to assign a user to get it activated\n  - Then execute\n      ```powershell\n        Add-AzureADDirectoryRoleMember -ObjectId '[App Admin Object Id]' -RefObjectId '[User Managed Identity Object Id]'\n      ``` \n  - Also assign the \"Directory Reader\" role in the same way to enable the terraform module `azure_api_roles' query the directory. Or use the `azure_api_roles_static' module where you have to check in the result json into the repository.\n      ```powershell\n        Add-AzureADDirectoryRoleMember -ObjectId '[Directory Reader Object Id]' -RefObjectId '[User Managed Identity Object Id]'\n      ``` \n\n## Connect Github Setup\nThe github actions require permissions to create the structure with terraform. Do the following steps to create and assign a ServicePrincipal to that specific Github Project' Environment if necessary.\n1. In Azure Open the Managed Identity go to Settings/Federated Credentials and click Add Credential and select the Federated credential scenario \"Configure a Github issued token...\"\n2. Add your Organization/Personal Accountname, enter the repository name and __environment__ name as Entity. Also choose a credential name for it.\n3. Click on Add\n4. Go to overview Page and save the following IDs from it\n  - Client ID\n  - Subscription ID\n  - Tenant ID (Open JSON View on the top right for that)\n5. Go on Github and open you repository and open Settings\n6. In Environments select \"new environment\" and enter the name of the __environment__ you chosen in the federated credential. then click on configure environment.\n7. Enter the following Environment __Secrets__ which you saved from the managed identites. The key names have to be exactly like that. The values you got from the federated credential.\n  - AZURE_CLIENT_ID=[Client ID]\n  - AZURE_SUBSCRIPTION_ID=[Subscription ID]\n  - AZURE_TENANT_ID=[Tenant ID]\n8. make sure that you have set up the environment name in any job that requires these credentials.\n  ```yaml\n    jobs:\n      terraform:\n        environment:\n          name: 'dev'\n  ```\n9. In the jobs where you need them add the with statement to make sure they are provided. The services should usually auto grab them otherwise you can map them.\n  ```yaml\n      with:\n        # auth-type: SERVICE_PRINCIPAL\n        client-id: ${{ secrets.AZURE_CLIENT_ID }}\n        tenant-id: ${{ secrets.AZURE_TENANT_ID }}\n        subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}\n  ```\n10. You are done here. Run the Action and check if it can authorize on azure for it.\n\n## Terraform Azure Storage Setup\nWhen you have a Storage Account for all Terraform states of all projects on your Tenant then create a Container `[projectname_env]` and\n1. Check if terraform azurerm backend is configured with use_azuread_auth = true\n2. Assign yourself as **Storage Data Contributor** to the container\n3. Assign the Github Managed Identity also **Storage Data Contributor** Permissions to the container\n\n## Debugging the app\nYou need the following Extensions into VS Code\n1. Python Debugger\n2. Python\n3. Pylance\n\nAfterward in __VSCode__ you can \n1. Open your project folder  \n2. On the left bar select \"Run and Debug\"\n3. Select Full Stack Debug\n4. And simply press __F5__. (It will compile the app and start a debugging session in chrome)\n5. Now you can set Breakpoints in each frontend and backend\n\n## Generate a production build (Frontend)\nTo generate a production compile of the frontend\n1. Navigate to frontend folder `cd ./frontend`\n2. Type `npm run build`\n3. It will create a build into ./__backend__/dist folder where fast-api will start it. `./backend/dist`\n\n## Adding Users to Application and commit requested Permissions\nTo enable users joining your application you have to do following\n1. Go to Azure Portal and Navigate to Entra Id -\u003e Enterprise Applications\n2. Select the generated Application (following the terraform vars it is [app_name]-dev - with dashes not underlines)  \n3. Go to Manage -\u003e Users and groups\n4. Add the users and groups which should have access to the application and select also their Role (in this example its \"User\" or \"Admin\"). It will take some while so refresh the page couple of times\n5. To enable the requested permissions go to Entra Id - App registrations - All Applications\n6. Select the generated Application (following the terraform vars it is [app_name]-dev - with dashes not underlines)  \n7. Go to Manage -\u003e API Permissions\n8. Click on \"Grant admin consent for [Your Tenant Name]\" and confirm\n9. The users should now be able to log on to your application and only able to navigate within their role.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkstrassheim%2Fultimate-web-stack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkstrassheim%2Fultimate-web-stack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkstrassheim%2Fultimate-web-stack/lists"}