{"id":37403602,"url":"https://github.com/oslokommune/okr-tracker","last_synced_at":"2026-01-16T05:48:29.870Z","repository":{"id":37098194,"uuid":"215286055","full_name":"oslokommune/okr-tracker","owner":"oslokommune","description":"A front-end application for tracking Objectives and Key Results (OKRs) and Key performance indicators (KPIs) for product teams with a Google Firebase backend.","archived":false,"fork":false,"pushed_at":"2025-12-05T07:13:33.000Z","size":33217,"stargazers_count":84,"open_issues_count":1,"forks_count":31,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-12-08T15:14:45.202Z","etag":null,"topics":["cloud-functions","dashboard","dataspeilet","firebase","kpi","okr","okr-tracker","vue"],"latest_commit_sha":null,"homepage":"","language":"Vue","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/oslokommune.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"contributing.md","funding":null,"license":null,"code_of_conduct":"CODE_OF_CONDUCT.md","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-10-15T11:51:31.000Z","updated_at":"2025-12-05T07:13:36.000Z","dependencies_parsed_at":"2023-10-02T16:48:16.958Z","dependency_job_id":"c8a0fcf8-99f3-44d2-9276-563de71cd381","html_url":"https://github.com/oslokommune/okr-tracker","commit_stats":null,"previous_names":[],"tags_count":73,"template":false,"template_full_name":null,"purl":"pkg:github/oslokommune/okr-tracker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oslokommune%2Fokr-tracker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oslokommune%2Fokr-tracker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oslokommune%2Fokr-tracker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oslokommune%2Fokr-tracker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oslokommune","download_url":"https://codeload.github.com/oslokommune/okr-tracker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oslokommune%2Fokr-tracker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28477421,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T03:13:13.607Z","status":"ssl_error","status_checked_at":"2026-01-16T03:11:47.863Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["cloud-functions","dashboard","dataspeilet","firebase","kpi","okr","okr-tracker","vue"],"created_at":"2026-01-16T05:48:29.742Z","updated_at":"2026-01-16T05:48:29.841Z","avatar_url":"https://github.com/oslokommune.png","language":"Vue","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OKR Tracker\n\n- [OKR Tracker](#okr-tracker)\n  - [Demo](#demo)\n  - [Project requirements](#project-requirements)\n  - [Clone and install](#clone-and-install)\n  - [Set up new instance](#set-up-new-instance)\n    - [Create Firebase project](#create-firebase-project)\n      - [Enable Google Auth in Firebase](#enable-google-auth-in-firebase)\n    - [Environment variables](#environment-variables)\n    - [Link project](#link-project)\n    - [Run locally](#run-locally)\n  - [Make Firestore ready for production](#make-firestore-ready-for-production)\n    - [Create mock data](#create-mock-data)\n      - [Generate mock data](#generate-mock-data)\n      - [Exporting mock data](#exporting-mock-data)\n      - [Update mock data](#update-mock-data)\n      - [Possible problems](#possible-problems)\n  - [Create Google Cloud API Gateway](#create-google-cloud-api-gateway)\n  - [Build and deploy](#build-and-deploy)\n  - [Lint and fix](#lint-and-fix)\n  - [Import production data from Cloud Firestore to local Firestore](#import-production-data-from-cloud-firestore-to-local-firestore)\n    - [Requirements](#requirements)\n    - [Export production data](#export-production-data)\n  - [Import production data](#import-production-data)\n  - [Automated Backup with Cloud Functions](#automated-backup-with-cloud-functions)\n    - [Requirements for automated backups](#requirements-for-automated-backups)\n    - [Automated Restore with Cloud Functions](#automated-restore-with-cloud-functions)\n  - [Supported providers](#supported-providers)\n    - [Microsoft integration](#microsoft-integration)\n    - [Google integration](#google-integration)\n  - [Common problems](#common-problems)\n\n## Demo\n\nIf you would like to check out how the application works, you can go to the demo-site and sign in with a test-user\n\n- Site: https://origo-okr-tracker.web.app\n- User/pass: testuser@okr.com / testuser\n\n## Project requirements\n\n- Node 20.x\n- Firebase 10.x\n- Firebase tools \u003e9.x\n- Firebase Blaze plan - Pay as you go\n\n## Clone and install\n\nClone repository and run install:\n\n```bash\nnpm install \u0026\u0026 cd ./functions \u0026\u0026 npm install \u0026\u0026 cd ..\n```\n\nInstall Firebase CLI:\n\n```bash\nnpm install -g firebase-tools\n```\n\n## Set up new instance\n\nFollow this guide to set up a new clean instance of the OKR-tracker. Please read the whole readme and not sequentially. There are some steps throughout the readme that are important to set up a new instance.\n\n### Create Firebase project\n\n- Create a [Google Firebase](https://firebase.google.com) project.\n- [Initialize the project](https://firebase.google.com/docs/cli#initialize_a_firebase_project) with Firebase CLI\n- Create a Google service account\n  - From the **Project Overview**, select **Service accounts**\n  - Click **Generate new private key**\n\n```bash\nfirebase functions:config:set\n  service_account=\"\u003cservice account private key json-file\u003e\"\n  storage.bucket=\"\u003cyour-storage-bucket-name\u003e\"\n```\n\nCat the whole service account private key json file into the environment key `service_account`.\n\n```bash\n\nzsh\nfirebase functions:config:set service_account=\"$(cat origo-okr-tracker-private-key.json)\"\n\nsh\nfirebase functions:config:set service_account=\"${cat origo-okr-tracker-private-key.json}\"\n\n```\n\n**Note: The private key string needs to have actual line breaks as opposed to `\\\\n` because of an issue with how Firebase stores environment variables. [Read more](https://github.com/firebase/firebase-tools/issues/371).**\n\n#### Enable Google Auth in Firebase\n\nWe use Google Auth to authenticate users and this needs to be enabled in the Firebase Console.\n\n**NOTE: This does not apply if you are only running this locally. We support Google and Microsoft as authentications**\n\n- Navigate to your project in the [Firebase console](https://console.firebase.google.com/)\n- Press the **Authentication**-button in the side menu\n- **Sign-in Method**-tab\n- Enable Google Auth\n\n### Environment variables\n\nGet your Firebase SDK snippet from your [Firebase Console](https://console.firebase.google.com/):\n\n- Navigate to **Project settings**\n- Under **Your apps**, find Firebase SDK snippet and press **Config**\n- Copy the following secrets to a `.env.production` file in the root directory.\n- Use also need `.env.local` to run this locally\n\n| Secret                        | Description                                                                                                |\n| ----------------------------- | ---------------------------------------------------------------------------------------------------------- |\n| `VITE_API_KEY`                | _from SDK snippet_                                                                                         |\n| `VITE_AUTH_DOMAIN`            | _from SDK snippet_                                                                                         |\n| `VITE_DATABASE_URL`           | _from SDK snippet_                                                                                         |\n| `VITE_PROJECT_ID`             | _from SDK snippet_                                                                                         |\n| `VITE_STORAGE_BUCKET`         | _from SDK snippet_                                                                                         |\n| `VITE_MESSAGING_SENDER_ID`    | _from SDK snippet_                                                                                         |\n| `VITE_APP_ID`                 | _from SDK snippet_                                                                                         |\n| `VITE_I18N_LOCALE`            | `nb-NO OR en-US`                                                                                           |\n| `VITE_REGION`                 | `europe-west2`                                                                                             |\n| `VITE_LOGIN_PROVIDERS`        | login providers allowed separated with hyphen - only implemented google, email. Ex: `google-email`         |\n| `VITE_HOST_URL`               | URL which points to cloud functions that are set up as API CRUD endpoints                                  |\n| `VITE_MICROSOFT_TENANT_ID`    | To limit the authentication to a certain TENANT, other wise everyone with a Microsoft account could log in |\n| `VITE_ORGANIZATION`           | Name of the organization                                                                                   |\n\n### Link project\n\n```bash\nfirebase use --add\n```\n\n### Run locally\n\nThe local development environment uses [Firebase Emulator Suite](https://firebase.google.com/docs/emulator-suite) for Firestore and Cloud Functions. There is no need to do anything, only run the development script and everything is set up with a local user through Google auth.\n\nRetrieve current Firebase environment configuration. This is needed for certain cloud functions to function locally.\n\n```bash\nfirebase functions:config:get \u003e ./functions/.runtimeconfig.json\n```\n\nStart Firebase emulators, import mock data and run the development server:\n\n```bash\nnpm run dev\n```\n\n## Make Firestore ready for production\n\nIf you want to deploy to production or staging, you need to create multiple collections manually. Go to the Firestore Database in the [Firebase Cloud Console](https://console.firebase.google.com/)\n\n- audit\n- departments\n- keyResults\n- kpis\n- objectives\n- organizations\n- periods\n- products\n- requestAccess\n- slugs\n- users\n- domainWhitelist (optional)\n\nThe collection `users` needs one document with the first user. Create a document and add the following fields:\n\n```json\n{\n  \"id\": \"\u003cemail the user is signing in with\",\n  \"email\": \"\u003cemail the user is signing in with\",\n  \"superAdmin\": true,\n  \"widgets\": {\n    \"itemHome\": {\n      \"children\": true,\n      \"missionStatement\": true,\n      \"progression\": true,\n      \"team\": true\n    },\n    \"keyResultHome\": {\n      \"details\": true,\n      \"notes\": true,\n      \"weights\": true\n    },\n    \"objectiveHome\": {\n      \"details\": false,\n      \"progression\": true,\n      \"weights\": true\n    }\n  }\n}\n```\n\n### Create mock data\n\n#### Generate mock data\n\nAfter successfully logging in to the OKR Tracker, navigate to the [Admin panel](http://localhost:8080/admin). Here you can create new organisations, departments and products to use as your mock data. On each object you can also create periods, objectives, key results and KPIs.\n\n#### Exporting mock data\n\nTo export your mock data run the following command:\n\n```bash\nfirebase emulators:export ./mock_data\n```\n\n#### Update mock data\n\nTo update existing mock data, simply run the export command above and confirm overwrite existing export.\n\n#### Possible problems\n\nFirebase now exports storage emulator as well, even if you don't use it. These new folders are not checked into git because they are empty and git does not add empty folders. If you are a user that has problems running the mock data, you will need to add two folders to the `/mock_data/storage_export` folder. These are `blobs` and `metadata`.\n\n## Create Google Cloud API Gateway\n\nIt is possible to set up open API end points for users outside of the OKR-tracker frontend to update progress of Key Results and KPI's. To do so, you only need to deploy all the functions as usual, and then give the users the Cloud Function URL, but we do not recommend to call the Cloud Function directly. The better approach would be to set up a Google Cloud API Gateway and then reroute all the calls to the right Cloud Function.\n\nWe have set up an OpenAPI specification which you can check out [here](./public/openapi.yaml).\n\nYou can read more about on how to set up an API Gateway [here](https://cloud.google.com/api-gateway/docs/quickstart).\n\nThe TL;DR is:\n\n- Enable [required services](https://cloud.google.com/api-gateway/docs/quickstart#enabling_required_services)\n- Create an API\n- Create a new service account which has the correct access rights - we use the roles `APIGateway Admin` dsds `Cloud Functions Invoker`\n- Create an API config\n- Create a gateway\n\nAfter an API Gateway has been set up, we have closed the gateway with an API Key, which means that you would need to create an API Key through the Google Cloud Console\n\nIf there are any questions regarding this, do not hesitate to get in contact with us and we will gladly help (i.e. create an issue)\n\n## Build and deploy\n\nBuild and deploy to production:\n\n```bash\nnpm run deploy\n```\n\n### Using GitHub Actions\n\nTo configure automatic deploy to Firebase Hosting on merge to `main` (triggered as part of the `pipeline.yml` workflow), add the following secrets to your GitHub repository:\n\n- `ENV_FILE_PROD`: Contains a dumped copy of the production dotenv file.\n- `FIREBASE_PROJECT_ID_PROD`: The Firebase Project ID.\n- `FIREBASE_SERVICE_ACCOUNT_PROD`: Exported JSON key for a GitHub Actions specific service account created for deploying to Firebase Hosting.\n\nSee the [Firebase documentation](https://firebase.google.com/docs/hosting/github-integration) for steps required to create these secrets, either by using the Firebase CLI or [manually](https://github.com/FirebaseExtended/action-hosting-deploy/blob/main/docs/service-account.md).\n\n## Lint and fix\n\n[ESlint](https://eslint.org) (including [Prettier](https://prettier.io/) configured to be executed as a linter rule) and [Stylelint](https://stylelint.io) are used for code formatting and linting. See configuration in the following files:\n\n```\n./.eslintrc.js\n./.prettierrc.js\n./.stylelintrc.js\n```\n\n```bash\nnpm run lint            # Run linter\nnpm run lint:fix        # Fix lint issues\nnpm run lint:style      # Run style linter\nnpm run lint:style:fix  # Fix lint issues found in styles\n```\n\n## Import production data from Cloud Firestore to local Firestore\n\nBased on [this tutorial](https://medium.com/firebase-developers/how-to-import-production-data-from-cloud-firestore-to-the-local-emulator-e82ae1c6ed8) with a few differences for our use case.\n\nThe newest version of the OKR Tracker uses the Firebase Local Emulator Suite, where you can play and test your data without being afraid of production changes. It is still in the early stages, which means that auth is still handled by the cloud firebase and not locally.\n\nWhen you start up the local Firestore emulator you can see that the Firestore is completely empty because we don't have any production data. This is an amazing way of working because you can do what ever you want without doing damages, but it's real life data that you most likely want to test and fix.\n\nWe are going to show you how you can export your production data to a GCP bucket or use an existing backed up bucket to import into your local Firestore.\n\n### Requirements\n\n```\n- Firebase CLI\n- Google Cloud SDK\n```\n\nHow to install [Google Cloud SDK](https://cloud.google.com/sdk/install) and [Firebase CLI](https://firebase.google.com/docs/cli)\n\n### Export production data\n\nLogin to Firebase and Google Cloud\n\n```bash\nfirebase login\ngcloud auth login\n```\n\nSee the list of your projects and connect to the on you'd like to export data from:\n\n```bash\nfirebase projects:list\nfirebase use \u003cyour project id\u003e\n\ngcloud projects list\ngcloud config set project \u003cyour project id\u003e\n```\n\nFor the sake of this how to, we'll be using `okr-tracker-production` (production) for gcloud, and `origo-okr-tracker` (development) for the Firebase. The reason is that we use auth from our development Firebase instance, and not from the production instance.\n\nIf you don't already have automated backups of your production data, we will need to export the production data to a backup on GCP:\n\n```bash\ngcloud firestore export gs://okr-tracker-production.appspot.com/\u003cbackup-folder-name\u003e\n```\n\nNow copy the new folder to your local machine, we are going to do this from our functions folder:\n\n```bash\ncd functions\ngsutil -m cp -r gs://okr-tracker-production.appspot.com/\u003cbackup-folder-name\u003e .\n```\n\nIf you already have automated backups of your production data, you don't need to export the production data, only import it. For this application our backup folder is not part of the Firebase storage bucket:\n\n```bash\ngsutil -m cp -r gs://okr-tracker-backup/\u003cYYYY-MM-DD\u003e\n```\n\n## Import production data\n\nTo import the production data into your local Firebase emulator, you will need a metadata-file on the root folder, named `firebase-export-metadata.json`:\n\n```json\n{\n  \"version\": \"8.6.0\",\n  \"firestore\": {\n    \"version\": \"1.11.5\",\n    \"path\": \"functions/\u003cbackup-folder-name\u003e\",\n    \"metadata_file\": \"functions/\u003cbackup-folder-name\u003e/\u003cbackup-folder-name\u003e.overall_export_metadata\"\n  }\n}\n```\n\nStart your local Firebase emulator suite with the imported data. Firebase will read the metadata-json file automatically.\n\n```bash\nfirebase emulators:start --import=./\n```\n\n## Automated Backup with Cloud Functions\n\nWe use cloud functions to backup our database every night and only keep backup of the last 14 days. If a backup is older than 14 days it gets automatically and permanently deleted from the storage bucket.\n\n### Requirements for automated backups\n\n- Firebase Blaze plan\n- Set IAM Permission\n- Manually create a storage bucket\n- Cloud function\n\nTLDR:\n\n- Navigate to **Google Cloud Console** and choose your project\n- Navigate to IAM \u0026 Admin - Your App Engine Service account needs the **Cloud Datastore Import Export Admin** role\n- Navigate to **Storage** – Create a storage bucket – Give it a rule to delete storage that is \u003e14 days old\n- Run the command `firebase functions:config:set storage.bucket=\"\u003cyour-storage-bucket-name\u003e\"`\n\n### Automated Restore with Cloud Functions\n\nThis is called automated restore but we still need to manually trigger a cloud function that does the restore from the Google Cloud Console\n\nTLDR:\n\n- From your Google Cloud Console navigate to **PubSub**\n- Create a topic and name it 'restore-backup'\n- Trigger the topic by publishing a message and the restore will be triggered\n\nGif of the process:\n\n![Gif of the process src: thecloudfunction-blog](./documentation/recovery.gif)\n\nSrc/Citation: [The cloud function blog](https://thecloudfunction.com/blog/firebase-cloud-functions-recovery-backups/)\n\n## Supported providers\n\nOKR-tracker supports for the time being only four login providers: Microsoft, Google, email/pass. If you are looking for other providers that firebase support, we would love for you to open up a PR with the needed changes.\n\n### Microsoft integration\n\nFor the Microsoft-integration a TENANT must be specified as the environment-variable VITE_MICROSOFT_TENANT_ID.\n\n### Google integration\n\nAnyone with a google-account can login. To limit domain you have to implement this somehwhere, e.g. in `set_user.js` - e.g. `if (!user.email.lowerCase().endsWith('oslo.kommune.no')) rejectAccess();`\n\n## Common problems\n\nIf there are some problems running the project locally, or you get an infinite spinner: inspect the console in the browser, your terminal or `firebase-debug.log` file for error messages. Some common messages when firing up the project for the first time:\n\n1. \"No such file or directory, scandir storage_export/metadata\"\n   1. You need to create two directories under `mock_data/storage_export` - `blobs` and `metadata`\n2. It looks like you're trying to access functions.config().service_account but there is no value there\n   1. Check if you have set the config key for service_account correctly. Read the readme again and se how you need to cat the private-key file correctly\n3. Missing permissions required for functions deploy. You must have permission iam.serviceAccounts.ActAs on service account\n   1. Open the [Google Cloud Console](https://console.cloud.google.com/) (check that you are in the correct project).\n   2. Go to IAM \u0026 Admin -\u003e Service Accounts\n   3. Find the service account and click on it\n   4. Click on the \"Permissions\" panel, then click `Grant Access`\n   5. Add your IAM member email address. For the role, select Service Accounts -\u003e Service Account User\n   6. Click Save\n4. Cannot read property `bucket` of underfined\n   1. Set the config key `storage.bucket`. Please read the readme again\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foslokommune%2Fokr-tracker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foslokommune%2Fokr-tracker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foslokommune%2Fokr-tracker/lists"}