├── .gitattributes ├── .vitepress ├── .gitignore ├── theme │ ├── tailwind.css │ ├── index.ts │ └── style.css ├── README.md └── config.mts ├── development ├── README.md └── library │ ├── back-end │ ├── conventions--sql.md │ ├── conventions--php.md │ └── conventions--laravel.md │ └── front-end │ ├── conventions--js.md │ ├── conventions--css.md │ ├── conventions--jsdoc.md │ └── conventions--vue.md ├── .gitignore ├── .prettierrc ├── public ├── README.md ├── favicons │ ├── favicon.ico │ └── apple-touch-icon.png └── images │ └── hydrogenlogo.svg ├── postcss.config.js ├── .github ├── renovate.json ├── workflows │ ├── auto_update_npm_updates.yml │ ├── spelling.yml │ └── format.yml └── config.yml ├── .typos.toml ├── guides ├── OKR │ ├── 00-benefits-of-okrs.md │ ├── 00-history-of-okrs.md │ ├── README.md │ ├── 02-cascading-okrs.md │ ├── 05-assess-your-okrs.md │ ├── 01-okr-cadence.md │ ├── 00-why-okrs.md │ ├── 04-stay-aligned-as-a-team.md │ └── 03-create-your-okrs.md ├── roles │ ├── support-engineer.md │ └── senior-developer.md ├── onboarding │ ├── onboarding--domain-knowledge.md │ ├── README.md │ └── onboarding--buddyGuide.md ├── people-operations │ ├── video-calls.md │ └── team-trips.md └── collaboration-tools.md ├── outdated ├── design-products │ ├── README.md │ ├── design-principles.md │ └── delivery-process.md ├── achieve-purpose │ ├── README.md │ ├── vision.md │ └── mission.md ├── development │ └── README.md └── scrum │ ├── backlog.md │ └── README.md ├── library ├── backend │ ├── README.md │ ├── conventions--sql.md │ ├── literature.md │ ├── SOLID.md │ └── conventions--php.md └── frontend │ ├── use-the-platform.md │ ├── README.md │ ├── conventions--css.md │ ├── conventions--js.md │ ├── literature.md │ ├── conventions--jsdoc.md │ └── conventions--vuejs.md ├── .editorconfig ├── CONTRIBUTING.md ├── tailwind.config.js ├── LICENSE ├── package.json ├── README.md ├── index.md └── images ├── agile-sprints.svg └── continuous-delivery.svg /.gitattributes: -------------------------------------------------------------------------------- 1 | *.md text eol=lf 2 | -------------------------------------------------------------------------------- /.vitepress/.gitignore: -------------------------------------------------------------------------------- 1 | /cache 2 | /dist 3 | -------------------------------------------------------------------------------- /development/README.md: -------------------------------------------------------------------------------- 1 | This directory is deprecated. 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore temporary files 2 | .DS_Store 3 | /node_modules 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "bracketSpacing": false, 3 | "singleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /public/README.md: -------------------------------------------------------------------------------- 1 | See https://vitepress.dev/guide/asset-handling#the-public-directory 2 | -------------------------------------------------------------------------------- /public/favicons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InteractionDesignFoundation/handbook/HEAD/public/favicons/favicon.ico -------------------------------------------------------------------------------- /.vitepress/theme/tailwind.css: -------------------------------------------------------------------------------- 1 | @import './style.css'; 2 | 3 | @tailwind base; 4 | @tailwind components; 5 | @tailwind utilities; 6 | 7 | -------------------------------------------------------------------------------- /public/favicons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InteractionDesignFoundation/handbook/HEAD/public/favicons/apple-touch-icon.png -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | 'postcss-import': {}, 4 | tailwindcss: {}, 5 | autoprefixer: {}, 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "local>InteractionDesignFoundation/.github:renovate-config-security-updates-only" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.typos.toml: -------------------------------------------------------------------------------- 1 | [files] 2 | extend-exclude = [ 3 | ".git/", 4 | ] 5 | ignore-hidden = false 6 | 7 | [default.extend-words] 8 | invokable = "invokable" 9 | 10 | [default.extend-identifiers] 11 | # Typos 12 | "Github" = "GitHub" 13 | -------------------------------------------------------------------------------- /development/library/back-end/conventions--sql.md: -------------------------------------------------------------------------------- 1 | The document is moved. 2 | New URL is [SQL conventions](../../../library/backend/conventions--sql). 3 | 4 | Please report/fix a broken link on the external source — we’ll remove these stub/redirect pages soon. 5 | -------------------------------------------------------------------------------- /development/library/front-end/conventions--js.md: -------------------------------------------------------------------------------- 1 | The document is moved. 2 | New URL is [JS conventions](../../../library/frontend/conventions--js). 3 | 4 | Please report/fix a broken link on the external source — we’ll remove these stub/redirect pages soon. 5 | -------------------------------------------------------------------------------- /development/library/back-end/conventions--php.md: -------------------------------------------------------------------------------- 1 | The document is moved. 2 | New URL is [PHP conventions](../../../library/backend/conventions--php.md). 3 | 4 | Please report/fix a broken link on the external source — we’ll remove these stub/redirect pages soon. 5 | -------------------------------------------------------------------------------- /development/library/front-end/conventions--css.md: -------------------------------------------------------------------------------- 1 | The document is moved. 2 | New URL is [CSS conventions](../../../library/frontend/conventions--css). 3 | 4 | Please report/fix a broken link on the external source — we’ll remove these stub/redirect pages soon. 5 | -------------------------------------------------------------------------------- /development/library/front-end/conventions--jsdoc.md: -------------------------------------------------------------------------------- 1 | The document is moved. 2 | New URL is [JSDoc conventions](../../../library/frontend/conventions--js). 3 | 4 | Please report/fix a broken link on the external source — we’ll remove these stub/redirect pages soon. 5 | -------------------------------------------------------------------------------- /development/library/front-end/conventions--vue.md: -------------------------------------------------------------------------------- 1 | The document is moved. 2 | New URL is [Vue conventions](../../../library/frontend/conventions--vuejs). 3 | 4 | Please report/fix a broken link on the external source — we’ll remove these stub/redirect pages soon. 5 | -------------------------------------------------------------------------------- /development/library/back-end/conventions--laravel.md: -------------------------------------------------------------------------------- 1 | The document is moved. 2 | New URL is [Laravel conventions](../../../library/backend/conventions--laravel). 3 | 4 | Please report/fix a broken link on the external source — we’ll remove these stub/redirect pages soon. 5 | -------------------------------------------------------------------------------- /guides/OKR/00-benefits-of-okrs.md: -------------------------------------------------------------------------------- 1 | # Benefits of OKRs 2 | 3 | ![](../../images/10-okr-benefits-part-1.svg) 4 | 5 | ![](../../images/11-okr-benefits-part-2.svg) 6 | 7 | ![](../../images/12-okr-benefits-part-3.svg) 8 | 9 | ![](../../images/21-transparency.svg) 10 | -------------------------------------------------------------------------------- /guides/OKR/00-history-of-okrs.md: -------------------------------------------------------------------------------- 1 | # OKR History 2 | 3 | ## Historical Development of OKRs 4 | 5 | ![](../../images/45-okr-history-people.svg) 6 | 7 | ## The OKR Approach and its Relation to Other Methods 8 | 9 | ![](../../images/46-okr-history-timeline.svg) 10 | -------------------------------------------------------------------------------- /outdated/design-products/README.md: -------------------------------------------------------------------------------- 1 | # Design Products 2 | 3 | ![](../../images/hero-design.svg) 4 | 5 | The IxDF Design Process is heavily informed by our [design principles](/outdated/design-products/design-principles.md) and enables us to [deliver](/outdated/design-products/delivery-process.md) value to our Members.. 6 | -------------------------------------------------------------------------------- /library/backend/README.md: -------------------------------------------------------------------------------- 1 | # Library: Backend 2 | 3 | ## Table of Contents 4 | 5 | - [IxDF conventions for PHP](conventions--php.md) 6 | - [IxDF conventions for Laravel](conventions--laravel.md) 7 | - [Clean Code Principles for PHP](clean-code-php.md) 8 | - [S.O.L.I.D. Principles for PHP](SOLID.md) 9 | - [Literature](literature.md) 10 | 11 | 🦄 12 | -------------------------------------------------------------------------------- /outdated/achieve-purpose/README.md: -------------------------------------------------------------------------------- 1 | # Achieve Our Purpose 2 | 3 | ![](../../images/hero-purpose.svg) 4 | 5 | The IxDF has a big purpose that requires us to work hard, and to work together, 6 | so each person in the IxDF must understand the **[Vision for the future of the IxDF](/outdated/achieve-purpose/vision.md)**, 7 | and carry out the daily **[Mission](/outdated/achieve-purpose/mission.md)** to bring about that vision. 8 | -------------------------------------------------------------------------------- /library/frontend/use-the-platform.md: -------------------------------------------------------------------------------- 1 | # #UseThePlatform 2 | 3 | A list of useful resources that follows #UseThePlatform principles: 4 | 5 | - [The Vanilla JavaScript Repository](https://vanillalist.top/) 6 | - [Web Components created by GitHub](https://github.com/search?q=topic%3Aweb-components+org%3Agithub&type=repositories) 7 | - [What PWA Can Do Today](https://whatpwacando.today/) 8 | - [Plain Vanilla](https://plainvanillaweb.com/) 9 | -------------------------------------------------------------------------------- /.github/workflows/auto_update_npm_updates.yml: -------------------------------------------------------------------------------- 1 | name: NPM PRs auto-merge 2 | 3 | on: 4 | schedule: 5 | - cron: "0 12 * * *" 6 | 7 | jobs: 8 | merge: 9 | name: "Auto-merge patch updates" 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: AnandChowdhary/dependabot-pr-action@master 13 | with: 14 | token: ${{ secrets.GITHUB_TOKEN }} 15 | merge-minor: false 16 | merge-patch: true 17 | -------------------------------------------------------------------------------- /.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | // https://vitepress.dev/guide/custom-theme 2 | import { h } from 'vue' 3 | import Theme from 'vitepress/theme' 4 | import './tailwind.css'; 5 | 6 | export default { 7 | extends: Theme, 8 | Layout: () => { 9 | return h(Theme.Layout, null, { 10 | // https://vitepress.dev/guide/extending-default-theme#layout-slots 11 | }) 12 | }, 13 | enhanceApp({ app, router, siteData }) { 14 | // ... 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /library/frontend/README.md: -------------------------------------------------------------------------------- 1 | # Library: Frontend 2 | 3 | ## Table of Contents 4 | 5 | - [IxDF conventions for JavaScript](conventions--js.md) 6 | - [IxDF conventions for JSDoc](conventions--jsdoc.md) 7 | - [IxDF conventions for Vue](conventions--vuejs.md) 8 | - [IxDF conventions for CSS](conventions--css.md) 9 | - [Clean Code Principles for JavaScript](clean-code-js.md) 10 | - [Literature](conventions--css.md) 11 | - [#UseThePlatform](use-the-platform.md) 12 | 13 | 🦄 14 | -------------------------------------------------------------------------------- /.vitepress/README.md: -------------------------------------------------------------------------------- 1 | # VitePress 2 | 3 | We use VitePress in a bit different way how it was intended to be used. We use it as a static site generator for our documentation. 4 | That's why we have additional steps during a building process. 5 | 6 | ## Build 7 | 8 | Build and preview: 9 | 10 | ```shell 11 | yarn docs:build 12 | yarn docs:preview 13 | ``` 14 | 15 | Live view (with live reload): 16 | 17 | ```shell 18 | yarn docs:dev 19 | ``` 20 | 21 | ## Materials 22 | 23 | - https://vitepress.dev/guide/getting-started 24 | -------------------------------------------------------------------------------- /.github/workflows/spelling.yml: -------------------------------------------------------------------------------- 1 | name: "Spelling" 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | push: 7 | branches: 8 | - "main" 9 | 10 | permissions: 11 | contents: "read" 12 | 13 | concurrency: 14 | group: "${{ github.workflow }}-${{ github.ref }}" 15 | cancel-in-progress: true 16 | 17 | jobs: 18 | typos_check: 19 | name: "Typos check" 20 | runs-on: ubuntu-latest 21 | timeout-minutes: 1 22 | steps: 23 | - uses: actions/checkout@v4 24 | 25 | - uses: crate-ci/typos@master 26 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | max_line_length = 120 11 | tab_width = 4 12 | block_comment_start = /* 13 | block_comment = * 14 | block_comment_end = */ 15 | 16 | [*.md] 17 | #indent_size = 2 18 | trim_trailing_whitespace = false 19 | max_line_length = 500 20 | 21 | [*.{yml,yaml}] 22 | indent_size = 2 23 | 24 | [yarn.lock] 25 | indent_size = 2 26 | max_line_length = unset 27 | 28 | [*.svg] 29 | max_line_length = unset 30 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Welcome to the Employee Handbook repository! 4 | We appreciate your interest in contributing to this project. 5 | This document outlines the guidelines for contributing to the Employee Handbook repository. 6 | Please take a moment to read through this guide to ensure a smooth and collaborative contribution process. 7 | 8 | ## Rules 9 | 10 | 1. Use American English as the standard written language. 11 | 1. Please keep clear file structure. 12 | 1. Do not create links like "here" or "click here". All links should have relevant anchor text that describes what they link to. 13 | -------------------------------------------------------------------------------- /outdated/achieve-purpose/vision.md: -------------------------------------------------------------------------------- 1 | # Vision for the future of the IxDF 2 | 3 | So, what’s the vision of the IxDF? What’s the future path for our mission, so to speak? 4 | What are we going to achieve together and strive towards, as a team – today and in the future? 5 | 6 | - To become the very best, the most well-known and the most prestigious design school in the world and the one-stop destination for designers to learn new skills 7 | - To have the very best learning platform, learning process and learning content for designers on the planet. 8 | - To have a true high-performance culture of high performance and excellence. 9 | -------------------------------------------------------------------------------- /.github/workflows/format.yml: -------------------------------------------------------------------------------- 1 | name: Format 2 | 3 | on: 4 | push: 5 | paths: 6 | - "**.md" 7 | - "**.json" 8 | 9 | jobs: 10 | prettier: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - uses: actions/setup-node@v4 16 | with: 17 | node-version: 20 18 | cache: 'yarn' 19 | 20 | - name: Install 21 | run: yarn install 22 | env: 23 | CI: true 24 | 25 | - name: Run formatting tool 26 | run: yarn style:fix 27 | 28 | - uses: stefanzweifel/git-auto-commit-action@v4 29 | with: 30 | commit_message: "✨ Apply formatting changes" 31 | env: 32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 33 | -------------------------------------------------------------------------------- /outdated/achieve-purpose/mission.md: -------------------------------------------------------------------------------- 1 | # Our Mission 2 | 3 | Our mission is to genuinely improve the world by creating design education of the highest quality and the lowest possible cost. 4 | We help as many designers, companies and students as possible improve their skills and future prospects—regardless of their location or background. 5 | This is the reason we exist. 6 | 7 | We LOVE that we make a big difference to millions of people around the world. 8 | 9 | Not only do we help millions build a better future for themselves, but we also teach them to apply their new design skills to improve the quality of life for humankind. 10 | We live in a world filled with inefficient and inhumane design—there lies a huge opportunity to make a positive impact through great design! 11 | -------------------------------------------------------------------------------- /guides/OKR/README.md: -------------------------------------------------------------------------------- 1 | # Coordinate Efforts 2 | 3 | ![](../../images/hero-coordination.svg) 4 | 5 | When you have a grand global [vision](/outdated/achieve-purpose/vision.md) 6 | and a [mission](/outdated/achieve-purpose/mission.md) to achieve that vision with the highest possible quality 7 | at the lowest possible cost for millions of people, you are only going to succeed with hard work and great team coordination. 8 | 9 | To achieve this at the IxDF, we hire unicorn team members, maintain a high-performance culture, 10 | and use frameworks like scrum, agile and OKRs (Objectives and Key Results). 11 | 12 | If you are not already familiar, you can learn more [about OKRs](./00-why-okrs), 13 | or about the [benefits of OKRs](./00-benefits-of-okrs). 14 | 15 | If you are already familiar and want to start using OKRs as an IxDF staff, 16 | please start with [our OKR cadence](./01-okr-cadence). 17 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: [ 4 | './index.md', 5 | './docs/.vitepress/**/*.{js,ts,vue}', 6 | './docs/**/*.md', 7 | './vitepress/**/*.{js,ts,vue}', 8 | './development/**/*.md', 9 | './development/**/**/*.md', 10 | './guides/**/*.md', 11 | './guides/**/**/*.md', 12 | './library/**/*.md', 13 | './library/**/**/*.md', 14 | './outdated/**/*.md', 15 | './outdated/**/**/*.md', 16 | './docs/**/*.md', 17 | ], 18 | theme: { 19 | extend: {}, 20 | screens: { 21 | 'sm': '640px', 22 | // => @media (min-width: 640px) { ... } 23 | 24 | 'md': '768px', 25 | // => @media (min-width: 768px) { ... } 26 | 27 | 'lg': '1056px', 28 | // => @media (min-width: 1056px) { ... } 29 | 30 | 'xl': '1280px', 31 | // => @media (min-width: 1280px) { ... } 32 | 33 | '2xl': '1536px', 34 | // => @media (min-width: 1536px) { ... } 35 | } 36 | }, 37 | plugins: [], 38 | } 39 | -------------------------------------------------------------------------------- /guides/OKR/02-cascading-okrs.md: -------------------------------------------------------------------------------- 1 | # Cascading OKRs 2 | 3 | What are Cascading OKR's? 4 | Like similar systems (e.g., [Cascading Stylesheets](https://developer.mozilla.org/en-US/docs/Web/CSS)), 5 | attributes and changes at one level of OKR are reflected in other levels of OKR. 6 | For example, when a new IxDF-wide OKR is created or changed and communicated by the IxDF Executive Level, 7 | each Team and Individual OKR as adjusted each quarter to support it. 8 | 9 | ![Image of cascading OKRs](../../images/24-okr-cascade-part-1.svg) 10 | 11 | This helps to align all of our individual, team, and organizational OKRs are aligned and helping to achieve the IxDF's mission and vision. 12 | 13 | ![Image of the quarterly IxDF OKR process](../../images/25-okr-cascade-part-2.svg) 14 | 15 | Here is what the process looks like over the course of a normal quarter. 16 | 17 | ![](../../images/26-okr-quarter-reference.svg) 18 | 19 | Now that you have seen how our OKRs work at the organizational level, it’s time to start [creating your OKR's](./03-create-your-okrs). 20 | -------------------------------------------------------------------------------- /guides/OKR/05-assess-your-okrs.md: -------------------------------------------------------------------------------- 1 | # Assess Your OKRs 2 | 3 | By the end of the quarter, you and your Team give each Key Result a final score, and reflect on your OKRs as a whole. Using a retrospective approach, pose some (or all) of these questions to your Team: 4 | 5 | - Were our Objectives ambitious enough? 6 | - Were our Key Results measurable? Did we know what our baseline was at the start of the quarter? 7 | - Did we “set ’em and forget ’em”? If so, why? 8 | - Were our OKRs aligned with the IxDF’s broader strategies? 9 | - Did they keep us focused on delivering value to customers? 10 | - Did we feel connected to our OKRs? 11 | - What have we learned from this quarter? How do we lift the bar moving into the coming quarter? 12 | 13 | ## Hold the Quarterly Meeting 14 | 15 | At the end of each quarter, you evaluate your own and your Team’s OKRs in order to measure your accomplishment 16 | 17 | ![](../../images/42-end-of-quarter-meeting-metrics.svg) 18 | 19 | ## The Meeting 20 | 21 | ![](../../images/43-end-of-quarter-meeting-team.svg) 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 The Interaction Design Foundation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /outdated/design-products/design-principles.md: -------------------------------------------------------------------------------- 1 | # Design Principles 2 | 3 | Design is the art of making smart, effective decisions that create a desirable outcome. We use a set of 11 Design Principles to help guide our decisions. We began with the Ten Principles of Good Design by Industrial Designer Dieter Rams which we continue to adapt for our own purposes. 4 | 5 | 1. Good design is **innovative**—It does not automatically follow convention. 6 | 1. Good design makes a product **useful**—It does work for people. 7 | 1. Good design is **aesthetically beautiful**—It makes your heart skip a beat. 8 | 1. Good design makes a product **understandable**—Anyone can use it instantly. 9 | 1. Good design is **unobtrusive**—It lets the content, learner, instructors shine. 10 | 1. Good design is **honest**—”I know exactly who designed this!” 11 | 1. Good design is **long-lasting**—Hot new trends don’t worry us. 12 | 1. Good design is **thorough** down to the last detail—We care about it all. 13 | 1. Good design is **good for everyone**—All people and the living things around them. 14 | 1. Good design is **as little design as possible**—If it doesn’t add value, it’s not going in the design. 15 | 1. Good design **teaches**—Experiencing it should help me then apply it 16 | -------------------------------------------------------------------------------- /guides/OKR/01-okr-cadence.md: -------------------------------------------------------------------------------- 1 | # OKR Cadence 2 | 3 | A good process is repeatable, has a good cadence. The IxDF OKR process is broken into 3-month cycles. 4 | 5 | ![Image of IxDF 3-month OKR cycle](../../images/14-okr-quarter-part-1.svg) 6 | 7 | At the start of each cycle, Quarterly Goals are set for the whole IxDF based on the [Vision](/outdated/achieve-purpose/vision.md) and [Mission](/outdated/achieve-purpose/mission.md). Teams and Individuals plan and align their OKRs and begin a series of six 2-week Sprints. 8 | 9 | ![](../../images/15-okr-quarter-part-2.svg) 10 | 11 | At the end of the cycle, each team has an OKR Retrospective to improve the OKR Process and an OKR Review to analyze the progress on each OKR. 12 | 13 | By aligning quarterly objectives with annual objectives that are set at the start of the year, it is possible to see how daily tasks contribute to key results, quarterly objectives, annual objectives and the IxDF mission and vision. 14 | 15 | ![](../../images/16-okr-year-and-quarter-part-1.svg) 16 | 17 | This then allows us to align our strategic goals and planning with our daily execution of tasks. 18 | 19 | ![](../../images/17-okr-year-and-quarter-part-2.svg) 20 | 21 | Below is a more detailed view of our yearly IxDF-wide OKR process. 22 | 23 | ![](../../images/18-okr-year.svg) 24 | 25 | And here is a view of what this looks like at the team level. 26 | 27 | ![](../../images/20-how-we-use-okrs-in-teams.svg) 28 | -------------------------------------------------------------------------------- /outdated/development/README.md: -------------------------------------------------------------------------------- 1 | # Develop Software 2 | 3 | ![](../../images/hero-development.svg) 4 | 5 | At IxDF, we're building an open and transparent company, full of people who love their work and enjoy the challenges they face every day. 6 | To achieve this, we want everyone to understand what is expected of them, the things we value and the things we believe should be avoided. 7 | 8 | ## Table of Contents 9 | 10 | - Guides 11 | - [Onboarding](/guides/onboarding/README.md) 12 | - People Operations 13 | - [Team Trips](/guides/people-operations/team-trips.md) 14 | - [Video Calls](/guides/people-operations/video-calls.md) 15 | - [Scrum](/outdated/scrum/README.md) 16 | - [Our expectations from you and your work](/guides/roles/senior-developer.md) 17 | - [Collaboration tools](/guides/collaboration-tools.md) 18 | - Library 19 | - [Back end](/library/backend/README.md) 20 | - [Front end](/library/frontend/README.md) 21 | 22 | ## Links 23 | 24 | - [Handbook contribution guide](/CONTRIBUTING.md): how to make this document even better 🦄 25 | - 🔒 Shared folders at [Dropbox.com](https://www.dropbox.com/share/) (ask **@mads** to give you access) 26 | - [🔒 developer docs](https://github.com/InteractionDesignFoundation/IxDF-web/blob/main/docs/README.md) - development-related documents 27 | 28 | ## The IxDF Zen Code 29 | 30 | ![image](https://user-images.githubusercontent.com/13465519/45677743-8445e980-bb67-11e8-9243-9ae29dea255a.png) 31 | 32 | 🦄 33 | -------------------------------------------------------------------------------- /guides/roles/support-engineer.md: -------------------------------------------------------------------------------- 1 | # Support engineer 2 | 3 | :::tip More you can find in internal documentation 4 | This is only a basic version of the documentation. 5 | [Full documentation](https://docs.information-architecture.org/workflows/roles/support-engineer.html) contains some content that we don’t want to open-source for security reasons. 6 | ::: 7 | 8 | [[toc]] 9 | 10 | By agreement, at least one engineer is assigned the support engineer role and usually stay on it for 1-2 weeks only. 11 | This role is usually assigned to developers who have just completed 12 | a large feature or some other large task who need some time to keep an eye on things and recover energy. 13 | 14 | ## Why do we have this role? 15 | 16 | The main goal is to allow other developers to focus on bigger tasks while support engineers work ongoing bug reports 17 | and help other teams with their tasks. 18 | 19 | ## Your responsibilities 20 | 21 | This role can be a challenging one as it involves a lot of critical thinking and initiative. 22 | In a nutshell, your goal is to protect the dev team from distractions while still making sure 23 | that the needs of the business are taking care of. 24 | 25 | You have done a great job as a support engineer when: 26 | 27 | 1. The dev team can confidently mute error channels and notifications knowing that you are constantly monitoring for errors and performance issues 28 | 2. The dev team can focus almost entirely on their sprint goals, knowing that you will only involve them if its really important that you do so 29 | 3. Other teams feel like their requests are being heard and taken care of in a timely manner 30 | -------------------------------------------------------------------------------- /guides/onboarding/onboarding--domain-knowledge.md: -------------------------------------------------------------------------------- 1 | # How to get domain knowledge 2 | 3 | We’ve developed a few onboarding activities to give you a much deeper understanding 4 | of our domain. Understanding our domain, i.e. the platform and its features from 5 | our **users’ perspective** (i.e. domain knowledge) is paramount to both understanding 6 | our codebase and writing awesome code. Great code has a **“small conceptual distance”** 7 | to the domain. In other words, it brings cognitive ease when variables, methods, database tables, 8 | models, services, operations, and likewise come directly from domain-specific vocabulary. 9 | 10 | Don’t expect to grasp/understand/remember everything you read during your onboarding. 11 | Look at it as a map which you can refer to down the road. 12 | 13 | ## Read docs from `/docs/domain` 14 | 15 | In our main repository we have [🔒 `/docs/domain/`](https://github.com/InteractionDesignFoundation/IxDF-web/tree/main/docs/domain) directory with README.md file for every system/module we have on our application. 16 | Such `README.md` files provide a brief overview of the system and usually contains links to other docs with deeper technical details. 17 | During onboarding, you need to read `README.md` files for every system. 18 | 19 | ## Test email notifications 20 | 21 | Go to the [notification control panel](https://develop.information-architecture.org/admin/notifications) 22 | on our staging/test sites (You can find the basic-auth credentials in lastpass). 23 | On that page, you will see information on how to test an email notification. 24 | 25 | Please be **absolutely sure** you’re not on the production server but on a **staging/test site**. 26 | 27 | Doing this activity can feel a bit grinding, but rest assured that it will pay off 28 | in the long run. It will make your work in the codebase considerably easier. 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ixdf-handbook", 3 | "description": "IxDF Company handbook for developers", 4 | "main": "README.md", 5 | "private": true, 6 | "type": "module", 7 | "scripts": { 8 | "test": "npm run style:lint", 9 | "style:lint": "prettier \"**/*.md\"", 10 | "style:fix": "prettier \"**/*.md\" --write", 11 | "docs:build": "vitepress build", 12 | "docs:dev": "vitepress dev", 13 | "docs:preview": "vitepress preview", 14 | "docs:fix": "prettier \"**/*.md\" --write" 15 | }, 16 | "engines": { 17 | "node": ">=20.0" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/InteractionDesignFoundation/handbook.git" 22 | }, 23 | "keywords": [ 24 | "handbook", 25 | "company culture", 26 | "engineering culture" 27 | ], 28 | "bugs": { 29 | "url": "https://github.com/InteractionDesignFoundation/handbook/issues" 30 | }, 31 | "homepage": "https://github.com/InteractionDesignFoundation/handbook#readme", 32 | "dependencies": { 33 | "autoprefixer": "^10.4.19", 34 | "husky": "^8.0.3", 35 | "mermaid": "^11.10.0", 36 | "postcss": "^8.4.39", 37 | "postcss-import": "^16.1.0", 38 | "prettier": "^3.1", 39 | "pretty-quick": "^3.1.3", 40 | "tailwindcss": "^3.4.4" 41 | }, 42 | "postcss": { 43 | "plugins": { 44 | "postcss-import": {}, 45 | "tailwindcss": {}, 46 | "autoprefixer": {} 47 | } 48 | }, 49 | "devDependencies": { 50 | "vitepress": "^1.0", 51 | "vitepress-plugin-mermaid": "^2.0.16", 52 | "vitepress-sidebar": "^1.18.5" 53 | }, 54 | "husky": { 55 | "hooks": { 56 | "pre-commit": "pretty-quick --staged" 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | In amazing things we trust 6 | 7 |

8 | 9 | # IxDF Dev Handbook 10 | 11 | At IxDF, we're building an open and transparent company, full of people who love their work and enjoy the challenges they face every day. 12 | To achieve this, we want everyone to understand what is expected of them, the things we value and the things we believe should be avoided. 13 | 14 | ## Table of Contents 15 | 16 | - Guides 17 | - [Onboarding](/guides/onboarding/README.md) 18 | - People Operations 19 | - [Team Trips](/guides/people-operations/team-trips.md) 20 | - [Video Calls](/guides/people-operations/video-calls.md) 21 | - [Collaboration tools](/guides/collaboration-tools.md) 22 | - Roles 23 | - [Senior Developer](/guides/roles/senior-developer.md) 24 | - [Support engineer](/guides/roles/support-engineer.md) 25 | - Library 26 | - [Back end](/library/backend/README.md) 27 | - [PHP conventions](/library/backend/conventions--php.md) 28 | - [Laravel conventions](/library/backend/conventions--laravel.md) 29 | - [Front end](/library/frontend/README.md) 30 | - [JS conventions](/library/frontend/conventions--js.md) 31 | - [JSDoc conventions](/library/frontend/conventions--js.md) 32 | - [Vue conventions](/library/frontend/conventions--vuejs.md) 33 | - [CSS conventions](/library/frontend/conventions--css.md) 34 | 35 | 🦄 36 | -------------------------------------------------------------------------------- /outdated/scrum/backlog.md: -------------------------------------------------------------------------------- 1 | # How to plan your backlog 2 | 3 | - When choosing issues for an upcoming sprint, you can use "6 ideal work hours per day" as a reference point. An ideal work hour is an hour spent on an issue with a complete focus — no interruptions. It makes 60 ideal work hours per sprint (30 hours per week). During these "ideal work hours" you're in complete focus/concentration, i.e. "in the zone". The rest of your time, you’ll spend on coordination, "work about work", small-ish issues, meetings, and lots of other stuff. 4 | - Search for issues with the label `urgency:X` (where X is a number from 8 to 10) assigned to you (for developers, this would usually be critical bugs). You should include them into your next sprint - or do them right now if you have an empty backlog. 5 | - After that, choose all unfinished "important"(1) issues from the previous sprint that you've not managed to finish. They should be carried over to the next sprint. 6 | - Next pick "important"(1) issues selected by ProductOwner as goals for next sprint. 7 | - Finally, choose any other issues that will fill up your backlog so you have enough to do for the following sprint. Remember to pick these issues on what will get us most effectively/efficiently towards our short/mid/long-term goals and our vision. 8 | - Don’t forget to include all critical issues and other urgent priority issues (if any) to the upcoming sprint. 9 | 10 | When you do the Sprint Planning, ahead of the Sprint Planning Meeting, then make sure to add `next sprint` label for all issues you are going to add to your backlog: it will help us to: 11 | 12 | - filter out all your planned issues for easier review 13 | - automatically move issues to your backlog (by using a script) 14 | 15 | --- 16 | 17 | (1) "important" issues are those that add value to our platform; either for our end users or our staff, ProductOwner defines them. We usually mark them by `importance: high` label. 18 | -------------------------------------------------------------------------------- /guides/people-operations/video-calls.md: -------------------------------------------------------------------------------- 1 | # Video Calls 2 | 3 | We're an all-remote company that allows people to work from almost anywhere in the world. 4 | We hire great people regardless of where they live, but with colleagues from 10+ timezones (and counting) 5 | it’s important for us to practice clear communication that helps us stay connected and get things done. 6 | For this, we use asynchronous communication as a start and are as open as we can be by communicating 7 | through issues tracker (GitHub), Slack channels, and placing an emphasis on ensuring that conclusions 8 | of offline conversations are written down. 9 | When we go **back and forth three times** we jump on a synchronous video call. 10 | These communication guidelines are meant to facilitate smooth communication in an ever-growing, all-remote company. 11 | 12 | 1. We start on time and do not wait for people. People are expected to join no later than the scheduled minute of the meeting (before :01 if it is scheduled for :00). The question 'is everyone here' is not needed. 13 | 1. Always turn on video — unless the bandwidth suffers, at which point one or more people switch to audio-only. 14 | 1. Be mindful of background noise in your end. If you are in a noisy place, that noise will get transmitted to everyone 15 | and will interrupt the team's concentration. In this case, you merely mute and unmute your microphone 16 | whenever you are speaking/not speaking. 17 | 1. Make eye contact and be mentally 110% there so the developer who's talking can feel your presence 18 | and not feel like talking to a computer screen :-) 19 | 1. Pay attention to other team members; they may ask for help, OR you may notice that they need help without directly asking. 20 | Especially the daily calls are a chance for all of us to be on the same page AND help others to save time & sanity so that we operate as efficiently as possible. 21 | 1. Make sure you've read and re-read the guidelines on [Scrum overview](/outdated/scrum/README.md) so that you, for example, don’t give lengthy updates on insignificant stuff ("..and then I corrected a typo on page XYZ..." :-) ) 22 | 23 | 🦄 24 | -------------------------------------------------------------------------------- /guides/OKR/00-why-okrs.md: -------------------------------------------------------------------------------- 1 | # About OKRs 2 | 3 | ## WHAT are Objectives And Key Results (OKRs)? 4 | 5 | The OKR method is a popular strategy for setting and achieving goals within organizations. Like most organizations, we use [Cascading OKRs](./02-cascading-okrs), that allows us to align our vision, mission, values and strategy with day-to-day objectives, work and key results. 6 | 7 | ![Diagram of OKR alignment](../../images/5-alignment.svg) 8 | 9 | And because the OKR method is collaborative, it allows us to realize our vision and mission in the best possible way, by connecting our organizational, team, and personal goals to measurable results while having all Team Members and Team Leads work together in one, unified direction. 10 | 11 | ## Anatomy of an OKR 12 | 13 | Every OKR has three parts—an Objective, a Key Result and a Task. 14 | 15 | ![Diagram of OKR alignment](../../images/7-okr-part-2.svg) 16 | 17 | ## OKR Examples 18 | 19 | Below are three example OKRs. 20 | 21 | ![Diagram of OKR alignment](../../images/8-okr-examples.svg) 22 | 23 | Note that in these examples the KPI's and tasks are combined. For example, in Example 02, "Develop five free articles" is a task, and "improve signups from X% to Y%" is a KPI that measures signups which indicates progress toward the Objective. 24 | 25 | ## WHY Do We Use OKRs? 26 | 27 | - OKRs bridge the gap between our [Vision](/outdated/achieve-purpose/vision.md), [Mission](../../outdated/achieve-purpose/mission.md), Strategy and the concrete Objectives and Key Results in our daily work. 28 | - OKRs help us create a weekly, quarterly, and yearly overview over how our daily tasks are connected to our vision, and therefore help us decide individually, and in our Teams, which steps are the best to take. 29 | - They help us track our individual and Team progress, create alignment in our Teams and across Teams so everyone moves towards achieving the same overall goals. 30 | - OKRs improve our focus and increase transparency within and across teams. 31 | 32 | ![](../../images/19-okr-pillars.svg) 33 | 34 | If you are still wondering, here are some more [benefits of OKRs](./00-benefits-of-okrs). 35 | Otherwise, if you are ready to start using OKRs at the IxDF, let's start with [our OKR cadence](./01-okr-cadence). 36 | -------------------------------------------------------------------------------- /.github/config.yml: -------------------------------------------------------------------------------- 1 | # Configuration for welcome - https://github.com/behaviorbot/welcome 2 | 3 | # Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome 4 | 5 | # Comment to be posted to on first time issues 6 | newIssueWelcomeComment: > 7 | Wow, it’s your first issue here! We are glad that you want to improve this repository 🚀 8 | 9 | # Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome 10 | 11 | # Comment to be posted to on PRs from first time contributors in your repository 12 | newPRWelcomeComment: > 13 | Thanks for opening this pull request 🦄! Do you want to improve your PR? - Please check out our [contributing guidelines](https://github.com/InteractionDesignFoundation/handbook/blob/main/resources/contributing.md). 14 | 15 | # Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge 16 | 17 | # Comment to be posted to on pull requests merged by a first time user 18 | firstPRMergeComment: > 19 | Congrats on merging your first pull request! 🎉🎉🎉 20 | 21 | ![image](https://media.giphy.com/media/5gXYzsVBmjIsw/giphy.gif) 22 | 23 | # It is recommended to include as many gifs and emojis as possible! 24 | 25 | # Configuration for request-info - https://github.com/behaviorbot/request-info 26 | 27 | # *Required* Comment to reply with 28 | requestInfoReplyComment: > 29 | We would appreciate it if you could provide us with more info about this issue/PR! 30 | 31 | # *OPTIONAL* default titles to check against for lack of descriptiveness 32 | # MUST BE ALL LOWERCASE 33 | #requestInfoDefaultTitles: 34 | # - update readme.md 35 | # - updates 36 | 37 | # *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given 38 | # requestInfoLabelToAdd: needs-more-info 39 | 40 | # *OPTIONAL* Only warn about insufficient information on these events type 41 | # Keys must be lowercase. Valid values are 'issue' and 'pullRequest' 42 | requestInfoOn: 43 | pullRequest: true 44 | issue: true 45 | 46 | # Configuration for sentiment-bot - https://github.com/behaviorbot/sentiment-bot 47 | 48 | # *Required* toxicity threshold between 0 and .99 with the higher numbers being the most toxic 49 | # Anything higher than this threshold will be marked as toxic and commented on 50 | sentimentBotToxicityThreshold: .7 51 | 52 | # *Required* Comment to reply with 53 | sentimentBotReplyComment: > 54 | Please be respectful of other users. 55 | 56 | # Note: the bot will only work if your repository has a Code of Conduct 57 | -------------------------------------------------------------------------------- /guides/people-operations/team-trips.md: -------------------------------------------------------------------------------- 1 | # Team Trips 2 | 3 | A team that meets together, stays together. 4 | Remote working does not mean working in isolation – we meet up with the rest of the team several times a year at spectacular locations, 5 | from exotic islands in Thailand to the breathtaking mountains of Patagonia in Argentina. 6 | 7 | “Ideas are worthless without execution” — that means we should maximize effect of our team-trips. 8 | To achieve that, we have a simple guide to use while working on the team trips. 9 | 10 | ## How to get the most out of the team trip 11 | 12 | Most of the time, we have daily work sessions to define the future of the IxDF. 13 | Human brains are unreliable when it comes to remember something in detail; that’s why we need the ideas written down as soon as they are discussed. 14 | After the team trip, we are going to execute over those ideas. 15 | 16 | ### 1. Using GitHub to make action plans 17 | 18 | GitHub is the IxDF’s main project management tool. We will be using [🔒 IxDF-web's Issues](https://github.com/InteractionDesignFoundation/IxDF-web/issues) to make action plans for whatever we talk in and out of the work sessions during the trip. 19 | To create a new issue, you can simply click [IxDF-web/issues](https://github.com/InteractionDesignFoundation/IxDF-web/issues). 20 | 21 | Here is a screenshot of a new issue, briefly explaining how you can customize it: 22 | 23 | 24 | 25 | After you fill out the details, remember to click on **Submit new issue**. :-) 26 | 27 | ### 2. Applying SMART criteria for action plans 28 | 29 | When making action plans for the future of the IxDF, make sure that it fits to the [SMART criteria](https://en.wikipedia.org/wiki/SMART_criteria): 30 | 31 | **STRETCH GOAL:** Increase the traffic on the IxDF website. 32 | 33 | - **S**pecific: Increase the incoming traffic to the UX-daily article pages on the IxDF website. 34 | - **M**easureable: Increase the traffic on the IxDF website to 50,000 per day. 35 | - **A**ssignable: Increase the traffic on the IxDF website by expanding our social media reach through ads. 36 | - **R**ealistic: Increase the traffic on the IxDF website from 40,000 per day to 50,000 per day. 37 | - **T**ime-bound: Increase the traffic on the IxDF website within the next 2 months. 38 | 39 | **SMART GOAL:** Increase the incoming traffic to the UX-daily article pages on the IxDF website from 40,000 visitors per day to 50,000 per day by expanding our social media reach through ads within the next 2 months. 40 | 41 | There will be a correlation between the ease of execution and how well the action plan fits the SMART criteria. It might not be super easy to apply this criteria while discussing ideas, but we will have more time later to improve our action plans, and discuss them further. 42 | 43 | 🦄 44 | -------------------------------------------------------------------------------- /library/backend/conventions--sql.md: -------------------------------------------------------------------------------- 1 | # IxDF's SQL conventions 2 | 3 | [[toc]] 4 | 5 | ## DATETIME vs TIMESTAMP vs biginteger 6 | 7 | **TL;DL: Use `DATETIME`** to store datetime values, and use `TIMESTAMP` to store metadata (such as when a record has been created, updated, or deleted). 8 | 9 | - DATETIME supported range '1000-01-01 00:00:00' to '9999-12-31 23:59:59'. 10 | - TIMESTAMP supported range '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC.” 11 | 12 | The default behavior for default values of timestamps in MySQL and/or MariaDB differs for the first timestamp declaration compared to subsequent timestamps: 13 | 14 | > If the explicit_defaults_for_timestamp system variable is disabled, the first TIMESTAMP column has both DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP if neither is specified explicitly. 15 | 16 | See [MySQL 5.7 Reference Manual](https://dev.mysql.com/doc/refman/5.7/en/timestamp-initialization.html) for more details. 17 | Note, `explicit_defaults_for_timestamp` is disabled by default. 18 | 19 | When we read DATETIME, we should always be aware about timezone, at least we should be sure that DATETIME uses a timezone you expect to receive. 20 | 21 | Let’s review a common edge case: daylight saving. On the same day, it’s possible to have the same time twice, 22 | and when you compare times, you should understand which time is greater. TIMESTAMP provides this opportunity, DATETIME not. 23 | 24 | 1. Sunday, 7 November 2021, 02:00:00 clocks are turned backward 1 hour to: 25 | 2. Sunday, 7 November 2021, 01:00:00 local standard time instead. 26 | 27 | As you can see, there are 01:00:00 2 times at the same day. 28 | 29 | ### biginteger and year 2038 problem 30 | 31 | [Year 2038 problem](https://en.wikipedia.org/wiki/Year_2038_problem) caused by the limitations of signed 32-bit integer 32 | that used to store timestamps in a lot of popular DB engines (including MySQL). 33 | The latest possible date is `03:14:07 UTC on 19 January 2038` ((2^31)-1 = 2,147,483,647 seconds after 1 January 1970). 34 | 35 | Should we care about this problem? — Yes and no. Currently, we don’t have any data-flows and requirements to store any 36 | info in DB with dates close to 2038 year (it’s possible to try to create a Meetup far in the future, not it’s not critical). 37 | Current possible option is to use `unsigned biginteger` (2^64 - 1) date type. 38 | But we expect that closer to 2035 a lot of companies will start to work on this problem, we’ll have more solutions and options 39 | to deal with it, so we decided to postpone solving this problem. 40 | 41 | ## Coding style 42 | 43 | Use an upper case for SQL keywords and functions: 44 | 45 | ```sql 46 | # GOOD 47 | SELECT MAX(sent_at) last_sent_at, notification_class FROM notification__notification_log GROUP BY notification_class 48 | 49 | # BAD 50 | select max(sent_at) last_sent_at, notification_class from notification__notification_log group by notification_class 51 | ``` 52 | 53 | 🦄 54 | -------------------------------------------------------------------------------- /.vitepress/config.mts: -------------------------------------------------------------------------------- 1 | import {defineConfig} from 'vitepress'; 2 | import {withMermaid} from 'vitepress-plugin-mermaid'; 3 | import {generateSidebar} from 'vitepress-sidebar'; 4 | 5 | // https://vitepress.dev/reference/site-config 6 | const config = defineConfig({ 7 | lang: 'en-US', 8 | title: 'IxDF Open Handbook', 9 | description: 'Handbook and guidelines for IxDF technical staff.', 10 | head: [ 11 | ['link', {rel: 'icon', href: '/favicons/favicon.ico'}], 12 | ['link', {rel: 'apple-touch-icon', href: '/favicons/apple-touch-icon.png'}], 13 | ['link', {rel: 'stylesheet', href: 'https://fonts.googleapis.com/css?family=Merriweather:400,400i,700|Source+Code+Pro|Source+Sans+Pro:400,400i,700&display=swap'}], 14 | ], 15 | themeConfig: { 16 | // https://vitepress.dev/reference/default-theme-config 17 | siteTitle: 'IxDF Open Handbook', 18 | editLink: { 19 | pattern: 'https://github.com/InteractionDesignFoundation/handbook/edit/main/:path', 20 | text: 'Edit this page on GitHub', 21 | }, 22 | lastUpdated: {text: 'Last Updated'}, 23 | search: { 24 | provider: 'local', 25 | }, 26 | logo: 'https://public-images.interaction-design.org/ixdf-brand/ixdf-logo.svg', 27 | nav: [ 28 | {text: 'IxDF Handbook', link: '/'}, 29 | {text: "🔐 Development Docs", link: "https://docs.information-architecture.org"}, 30 | {text: 'UI Kit', link: 'https://ui-kit.interaction-design.org/'}, 31 | {text: 'We\'re hiring!', link: 'https://www.interaction-design.org/about/careers'}, 32 | ], 33 | 34 | // see https://github.com/jooy2/vitepress-sidebar 35 | sidebar: generateSidebar({ 36 | useTitleFromFileHeading: true, 37 | capitalizeFirst: true, 38 | hyphenToSpace: true, 39 | collapseDepth: 1, 40 | excludeFiles: [ 41 | 'README.md', 42 | 'CONTRIBUTING.md', 43 | ], 44 | excludeFolders: [ 45 | 'node_modules', 46 | 'development', 47 | 'outdated', 48 | ], 49 | }), 50 | }, 51 | 52 | markdown: { 53 | lineNumbers: false, 54 | 55 | // options for @mdit-vue/plugin-toc 56 | // https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc#options 57 | toc: {level: [2, 3]}, 58 | }, 59 | 60 | ignoreDeadLinks: [ 61 | /\.neon/, 62 | /\.php/, 63 | /ocramius/, 64 | ], 65 | appearance: false // This disables the dark mode toggle 66 | }); 67 | 68 | // eslint-disable-next-line import/no-default-export 69 | export default withMermaid({ 70 | ...config, 71 | // optionally, you can pass MermaidConfig 72 | mermaid: { 73 | // refer https://mermaid.js.org/config/setup/modules/mermaidAPI.html#mermaidapi-configuration-defaults for options 74 | }, 75 | }); 76 | -------------------------------------------------------------------------------- /library/frontend/conventions--css.md: -------------------------------------------------------------------------------- 1 | # IxDF's CSS conventions 2 | 3 | [[toc]] 4 | 5 | ## PostCSS 6 | 7 | We use `postcss-preset-env` and CSS features from [stage 3+](https://preset-env.cssdb.org/features#stage-3). 8 | 9 | ### Reduce the cognitive load 10 | 11 | - Use as many native CSS features as possible; 12 | - SHOULD not use PostCSS magic like `&` (exceptions: pseudo-elements and pseudo-classes and `@media` rules); 13 | - SHOULD not use nesting, because BEM names are unique enough (exceptions: pseudo-elements and pseudo-classes and `@media` rules); 14 | 15 | ## CSS Class Naming conventions 16 | 17 | We use [ITCSS](http://www.creativebloq.com/web-design/manage-large-css-projects-itcss-101517528): superset of 18 | [BEM](http://getbem.com/introduction/) CSS methodology. 19 | 20 | - [ITCSS architecture](https://www.xfive.co/blog/itcss-scalable-maintainable-css-architecture/) 21 | - [ITCSS: Harry Roberts - Managing CSS Projects with ITCSS (video)](https://youtu.be/1OKZOV-iLj4?t=404) 22 | - [BEM quick-start](https://en.bem.info/methodology/quick-start) 23 | - [Battling BEM CSS: 10 Common Problems And How To Avoid Them](https://www.smashingmagazine.com/2016/06/battling-bem-extended-edition-common-problems-and-how-to-avoid-them/) 24 | 25 | Additionally, we prefer to use camelCase, as follows: 26 | 27 | ```css 28 | .blockName { 29 | } 30 | .blockName__elementName { 31 | } 32 | .blockName__elementName--modifierName { 33 | } 34 | ``` 35 | 36 | ## Utility classes 37 | 38 | Along with our BEM-based classes, we have our utility classes. For all components and page specific classes we use BEM but when it comes to utility classes we have chosen to follow [Tailwind 3](https://tailwindcss.com/). This makes it easier for any new developer to come in to our project and know classnames without even having to go through our docs. Examples of utility classes 39 | 40 | ```html 41 |
42 |
43 |
44 |
45 | ``` 46 | 47 | ### Using utility classes 48 | 49 | Whenever a function can be performed using utility classes, then the utility class should be used instead of creating custom BEM classes. One of the most common example is margin and padding utility classes that are needed in almost every page. 50 | 51 | ```html 52 |
53 |
54 |
55 |
56 | ``` 57 | 58 | ### Using BEM along with utility classes 59 | 60 | Sometimes a page will require its custom CSS, and in that case, it is good to combine utility classes along with the BEM bases classes for the page/component. 61 | 62 | ```html 63 |
64 | 65 |
66 | ``` 67 | 68 | This [article](https://css-tricks.com/building-a-scalable-css-architecture-with-bem-and-utility-classes/) provides excellent guidelines for using BEM, utility classes and using them together. 69 | 70 | ## Files naming conventions 71 | 72 | Filenames should also use BEM + camelCase notation (same naming conventions above for CSS/PostCSS). The file structure for 73 | a CSS component would look like this: 74 | 75 | ``` 76 | /components 77 | /inputGroup 78 | inputGroup.css 79 | inputGroup--small.css 80 | inputGroup--big.css 81 | inputGroup.md 82 | . . . 83 | ``` 84 | -------------------------------------------------------------------------------- /guides/roles/senior-developer.md: -------------------------------------------------------------------------------- 1 | # Expectations from Developers 2 | 3 | We are a small team of senior developers, and the IxDF does not employ junior or medium level developers. 4 | That’s why this list only includes our expectations for senior developers. 5 | 6 | ## Senior developer 7 | 8 | 1. A senior developer understands and is aligned with the IxDF Company Culture which is **very** thoroughly explained in our "IxDF Company Culture Course" (taken during your onboarding phase). 9 | 1. **Seriousness firstly means "responsibility"**. Responsibility for your decisions, solutions, code, and communication with the team. 10 | 1. A senior developer is [able to carry a message to Garcia](https://courses.csail.mit.edu/6.803/pdf/hubbard1899.pdf): 11 | They **can take the initiative** when carrying out a challenging assignment. 12 | 1. A senior developer **has experience**; because they are able to learn from their mistakes. 13 | 1. A senior developer **helps their team get better every day**. E.g. by energizing his/her colleagues on group calls, setting an example of awesome code that awes the rest of the team, inspiring colleagues with his/her results/help, etc. etc. 14 | 1. A senior developer **finds and fixes the root causes of the problem** and not just the symptoms. 15 | 1. A senior developer can **self-reliantly deliver working software**. 16 | 1. A senior developer understands that their job is to **provide solutions to problems**, not to write code. 17 | 1. A senior developer [**knows their tools**](https://stitcher.io/blog/craftsmen-know-their-tools): IDE, OS/terminal, debugging, static analyzers, formatters, test frameworks, CI, CD, etc. 18 | 1. A senior developer **knows how to choose the right tool and framework**. 19 | 1. A senior developer actively employs the Boyscout principle and helps update this documentation ("always leave the campground cleaner than you found it") 20 | 1. **Most importantly**, a senior developer reminds us all, or reminds a given individual developer, when we do not live up to what’s written on this page, written in the [IxDF Zen Code](../../outdated/development/README.md#the-ixdf-zen-code), taught in the IxDF Culture Course, or considered a best practice among senior developers. A senior developer is thus a "guarantor" that we continually optimize our team spirit, fun, productivity, learning, results, impact on the world, and programming practices. 21 | 22 | ### Senior backend developer 23 | 24 | This list is an extension of our expectations from a senior developer (see the previous section). 25 | 26 | 1. Broad and extensive knowledge of the software development process and its technologies. 27 | 1. Strong understanding of the primary programming language used in IxDF. 28 | 1. Experience in using object-oriented design principles and patterns. 29 | 30 | ### Senior frontend developer 31 | 32 | This list is an extension of our expectations from a senior developer (see the previous section). 33 | 34 | 1. Strong knowledge of HTML and at least one modern JS framework and an understanding of how it works. 35 | 1. Middle-level knowledge of at least one different JS framework OR strong understanding of design patterns. 36 | 37 | ## Short articles to read 38 | 39 | Now, please read the following articles: 40 | 41 | 1. [So You Want To Be a Senior Developer?](https://css-tricks.com/want-senior-developer/) 42 | 1. [The Role of a Senior Developer](https://web.archive.org/web/20160609115315/http://mattbriggs.net/blog/2015/06/01/the-role-of-a-senior-developer/) 43 | 44 | 🦄 45 | -------------------------------------------------------------------------------- /library/backend/literature.md: -------------------------------------------------------------------------------- 1 | # IxDF's Literature for back-end developers 2 | 3 | > You are reading this [...] for two reasons. First, you are a programmer. Second, you want to be a better programmer. Good. We need better programmers. 4 | > 5 | > -Robert C. Martin (from Clean Code) 6 | 7 | We have, again and again, experienced that it’s not enough to be a good developer — let alone be a developer. We also have 8 | experienced in our team that once a developer has studied the correct content, the code quality and the collective peace of mind 9 | have multiplied. That’s why we have curated a great deal of material for ourselves to become better. 10 | 11 | > The frenetic rate of change in our industry means that software developers must continue to learn copious quantities just to keep up. 12 | > Woe to the architects who stop coding—they will rapidly find themselves irrelevant. Woe to the programmers who stop learning new 13 | > languages—they will watch as the industry passes them by. Woe to the developers who fail to learn new disciplines and techniques—their 14 | > peers will excel as they decline. 15 | > 16 | > -Robert C. Martin (from Clean _Coder_) 17 | 18 | ## Index 19 | 20 | You can find all books, articles and videos on the shared folder `IxDF - Shared Reading - Library of Dev literature`. 21 | 22 | ### Reading list 23 | 24 | 1. Classic programming (books): `Robert Martin - Clean Code - 2008` and/or `Steve McConnell - Code Complete, 2nd edition - 2014`. 25 | 1. Framework: Official Laravel [documentation](https://laravel.com/docs/) :smile: 26 | 1. Design Patterns (book): `Erich Gamma, Richard Helm, Ralph Johnson, John M. Vlissides - Design Patterns - 1994` , `Eric Freeman - Head First Design Patterns - 2004`, or [Dive Into design patterns](https://refactoring.guru/design-patterns/book) 27 | 1. Server management (book): `Chris Fidao - Servers for Hackers - 2016.pdf`. 28 | 1. Clean Architecture (book): `Robert Martin - Clean Architecture: A Craftsman's Guide to Software Structure and Design - 2017`. 29 | 1. Topic: 30 | [S](https://code.tutsplus.com/tutorials/solid-part-1-the-single-responsibility-principle--net-36074). 31 | [O](https://code.tutsplus.com/tutorials/solid-part-2-the-openclosed-principle--net-36600). 32 | [L](https://code.tutsplus.com/tutorials/solid-part-3-liskov-substitution-interface-segregation-principles--net-36710). 33 | [I](https://code.tutsplus.com/tutorials/solid-part-4-the-dependency-inversion-principle--net-36872). 34 | [D](https://code.tutsplus.com/tutorials/solid-part-4-the-dependency-inversion-principle--net-36872). 35 | principles ([short version](https://jokiruiz.com/software/solid-principles-php/)). There are also videos on the topic inside `SOLID Principles in PHP` directory. 36 | 1. Topic: 37 | [KISS, YAGNI & DRY Principles](https://code.tutsplus.com/tutorials/3-key-software-principles-you-must-understand--net-25161). 38 | 1. Optional: TDD in Laravel: [`Course videos for Test-Driven Laravel`](https://course.testdrivenlaravel.com/) video course. 39 | 1. Optional: Classic programming (book): `Hunt A., Thomas D. - The Pragmatic Programmer. From Journeyman to Master - 1999`. 40 | 1. Optional: DDD (book): `Vernon V. - Domain-Driven Design Distilled - 2016`. 41 | 1. Optional: Articles inside `Articles` shared folder. 42 | 43 | ## Subscriptions 44 | 45 | Subscriptions are a great way to keep up with the latest news and trends in the industry. Here are some of the best ones: 46 | 47 | Newsletters: 48 | 49 | 1. [PHP Annotated Monthly](https://blog.jetbrains.com/phpstorm/tag/php-annotated-monthly/) digests by JetBrains 50 | 1. [Laravel news weekly newsletter](https://laravel-news.com/newsletter) 51 | 52 | YouTube: 53 | 54 | 1. [Laracon EU](https://www.youtube.com/channel/UCb9XEo_1SDNR8Ucpbktrg5A) annual Laravel conference videos on YouTube. 55 | 1. [PHP UK Conference](https://www.youtube.com/@phpukconference/videos) 56 | 1. [PHP Annotated](https://www.youtube.com/@phpannotated/videos) by JetBrains 57 | 58 | Blogs: 59 | 60 | 1. Freek’s (from Spatie) blog on Laravel & PHP: [freek.dev](https://freek.dev) 61 | 1. Brent’s Roose blog on Laravel & PHP: [stitcher.io](https://stitcher.io/blog) 62 | 1. Tim MacDonald blog: [timacdonald.me](https://timacdonald.me/) 63 | 64 | ## References 65 | 66 | 1. [Clean Code concepts adapted for PHP](clean-code-php.md) 67 | 1. [IxDF’s back-end conventions](README.md) 68 | 69 | 🦄 70 | -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | --- 2 | # https://vitepress.dev/reference/default-theme-home-page 3 | layout: home 4 | 5 | hero: 6 | name: 'IxDF Open Handbook' 7 | tagline: 'Open handbook for developers (Laravel+JS) created by the IxDF tech team.' 8 | actions: 9 | - theme: ghost 10 | text: Start here 11 | link: /README.md 12 | - theme: ghost 13 | text: Backend dev docs 14 | link: /library/backend/README.md 15 | - theme: ghost 16 | text: Frontend dev docs 17 | link: /library/frontend/README.md 18 | --- 19 | 20 |
21 |

IxDF Zen Code

22 |
23 |
24 |

Development

25 |
    26 |
  • Explicit is better than implicit.
  • 27 |
  • Delegate work to tool when possible.
  • 28 |
  • Simple is better than complex.
  • 29 |
  • Complex is better than complicated.
  • 30 |
  • Flat is better than nested.
  • 31 |
  • Errors should never pass silently.
  • 32 |
  • There should be one (and preferably only one) obvious way to do it.
  • 33 |
  • It should be easy to do run popular actions.
  • 34 |
  • Bad stuff should be difficult to do.
  • 35 |
  • If the implementation is hard to explain, it's a bad idea.
  • 36 |
  • If the implementation is easy to explain, it may be a good idea.
  • 37 |
38 |

Team

39 |
    40 |
  • We celebrate our achievements and encourage everyone to contribute.
  • 41 |
  • We all have decision-making authority, and everyone in the team is committed to each other's success.
  • 42 |
  • We have a flat hierarchy; everyone does everything possible to never fail one another.
  • 43 |
  • We don't punish anyone for making mistakes.
  • 44 |
  • We care about communication; we believe the "how" in communication is as important as the "what".
  • 45 |
46 |
47 |
48 |

Productivity

49 |
    50 |
  • We believe motivation and productivity come naturally when you work on something you're passionate about.
  • 51 |
  • We are action-oriented and strong believers in the maxim "ideas are worthless without execution."
  • 52 |
  • We have enormous degrees of freedom because we are able to live up to that responsibility.
  • 53 |
  • We finish what we have started; we don't feel good until we've carved a unicorn out of the monster.
  • 54 |
  • We know that even small tasks can give us emotional rewards when we know why we are doing them.
  • 55 |
  • We set audacious but achievable goals by breaking them into small and concrete plans.
  • 56 |
  • We welcome critique; we use our mistakes in a constructive way to become stronger.
  • 57 |
58 |

Community

59 |
    60 |
  • We exist, because our community exists.
  • 61 |
  • Our codebase reflects the high expectations of our community.
  • 62 |
  • We constantly reshape our platform and codebase based on our community's needs.
  • 63 |
  • We believe our platform and community will make the world a better place.
  • 64 |
65 |
66 |
67 |
68 | 69 |
70 |

Quick links: Coding conventions

71 | 77 |
78 | -------------------------------------------------------------------------------- /guides/collaboration-tools.md: -------------------------------------------------------------------------------- 1 | # Collaboration tools 2 | 3 | Collaboration is a keystone in IxDF’s success, and we couldn't make it happen without the right tools and processes. 4 | These are the tools we use almost every day. 5 | 6 | Please note that you should be using your company email address with all the tools listed below (except probably GitHub). 7 | 8 | ## [GitHub](https://github.com/InteractionDesignFoundation) 9 | 10 | Our issue tacker and code storage. [GitHub Actions](https://github.com/features/actions) is our CI/CD. 11 | 12 | Usage of [2FA](https://github.com/settings/security) is required. We also use real face photos for a profile picture to look more friendly to your colleagues. 13 | 14 | ## [Asana](https://app.asana.com/) 15 | 16 | Developers collaborate with other teams here. This is the main task tracker and project management tools for non-dev teams. 17 | Use your Google account to join the company on Asana. 18 | 19 | ## [Slack](https://slack.com/download) 20 | 21 | We use [Slack](https://slack.com/download) as our main tool for written communication and important notifications. 22 | Unless you're deep in the flow (state), you should be paying attention to what’s going on there. 23 | 24 | We also use real face photos for a profile picture to look more friendly to your colleagues. 25 | 26 | ### Do Not Disturb Hours 27 | 28 | Slack now supports "Do Not Disturb Hours" so you won’t be pinged in the middle of the night or while you are dealing with family matters. 29 | You can set your "Do Not Disturb Hours" by clicking on the bell at the top of the left pane in the Slack app. 30 | You also have the option of snoozing for 20 minutes or up to 24 hours. 31 | 32 | ## [Zoom](https://zoom.us) 33 | 34 | Zoom is our preferred tool to take video calls. To set up a Zoom meeting, [sign up for a free basic account](https://zoom.us/signup) using your IxDF team email address, and share the link for your "personal meeting room" with your participants. 35 | Note that on the Basic license, meetings are capped at 100 people, and meeting durations are capped at 40 minutes. 36 | 37 | ## [Google Calendar](https://calendar.google.com) 38 | 39 | We use Google Calendar to share info about our events: meetings, call, team-trips, etc. 40 | 41 | Recommendation: consider to have 2 different calendars on your IxDF google account: **public** and **private**. 42 | 43 | There are several benefits and reasons to sharing your calendar with everyone at IxDF: 44 | 45 | 1. Transparency is one of our values and sharing what you work on is in line with our message of "be open about as many things as possible". 46 | 1. Due to our timezone differences, there are small windows of time when our availabilities overlap. 47 | If other members need to schedule a new meeting, seeing the details of recurring meetings (such as 1-1s) will 48 | allow for more flexibility in scheduling without needing to wait for a confirmation from the team member. 49 | This speaks to our value to be more efficient. 50 | 51 | ### Modifying Events 52 | 53 | Please click 'Guests can modify event' so people can update the time in the calendar instead of having to reach out via other channels. 54 | You can configure this to be checked by default under [Event Settings](https://calendar.google.com/calendar/b/1/r/settings). 55 | 56 | ![image](https://user-images.githubusercontent.com/5278175/55792101-928a3180-5ac8-11e9-81d5-f56d62eea0fe.png) 57 | 58 | ## [Dropbox](https://www.dropbox.com/) 59 | 60 | We need a secure way of sharing files, and [Dropbox](https://www.dropbox.com/) is one of the best tools out there for this purpose. 61 | Via Dropbox you will get access to our literature library, exported designs and pretty much any other file you need to do your work. 62 | 63 | When you see the phrase "shared folders", we mean the "shared folders" on Dropbox. 64 | 65 | ## [Figma](https://figma.com) 66 | 67 | We also use Figma(https://figma.com) to share designs. Ask for an invitation in case you need to access anything on Figma. 68 | 69 | ## [LastPass](https://www.lastpass.com) 70 | 71 | We use LastPass to share login credentials, API keys and some top secret information. :-) 72 | 73 | ## [Downnotifier](https://downnotifier.com/) 74 | 75 | Sends an alert when your website is down (via SMS). 76 | **Please [add your cell phone number](https://www.downnotifier.com/list/edit?id=628289) to receive text messages in case of emergency**. 77 | 78 | ## Ye Olde Email 79 | 80 | Yeah, we still use email (and pigeons) from time to time, but make sure to check your email after pushing a new change 81 | since you will receive a notification in case the build (CI) fails. 82 | To make email less dull, we ask new team members to upload their most handsome/beautiful picture with a big smile! 83 | 84 | Also, please ensure that you have easy access to check your company email inbox (consider installing a browser extension such as 85 | [Chrome](https://chrome.google.com/webstore/detail/notifier-for-gmail/dcjichoefijpinlfnjghokpkojhlhkgl?hl=en), 86 | [Firefox](https://addons.mozilla.org/en-US/firefox/addon/gmail-notifier-restartless/), 87 | [Safari](https://safari-extensions.apple.com/details/?id=com.add0n.simple-notifier-RED8XKG2R4) 88 | or use mail client). 89 | 90 | 🦄 91 | -------------------------------------------------------------------------------- /guides/OKR/04-stay-aligned-as-a-team.md: -------------------------------------------------------------------------------- 1 | # Stay Aligned as a Team 2 | 3 | To make the OKR process work, we have to stay aligned as a team every day, week and month. 4 | At the IxDF, we use two-week Sprints to plan and execute our tasks. 5 | Each Sprint begins with a planning meeting. 6 | 7 | ## Prepare Yourself for a Sprint Planning Meeting 8 | 9 | ![](../../images/35-sprint-planning-prep.svg) 10 | 11 | _Note: We use Agile/Scrum in all our teams. It’s really just a fancy word for something simple so don’t be scared about the terminology or think you need to read books about it. There is some background information on how the Dev Team uses Scrum [here](https://handbook.interaction-design.org/development/guides/scrum/)._ 12 | 13 | Prepare yourself before a Sprint Planning Meeting 14 | 15 | 1. Go to the Spreadsheet “IxDF OKR Planning.xlsx” in the folder [IxDF / IxDF - PeopleAndCulture - Job Roles and Organizational Structure](https://www.dropbox.com/home/IxDF%20-%20PeopleAndCulture%20-%20Job%20Roles%20and%20Organizational%20Structure) on our DropBox instance—Available only to IxDF team members. 16 | 2. If this is your first time, then please CAREFULLY STUDY the tab “Sprint Planning Template” – and read all the “help bubbles”. 17 | 3. Find the tab in the spreadsheet called “Sprint Planning Team XYZ” where “XYZ” is your Team. 18 | 4. If that tab doesn’t exist, then create a copy of the tab “Sprint Planning Template” can call it “Sprint Planning Team XYZ” where “XYZ” is your Team. 19 | 5. Start editing/adding your tasks based on the instructions in the “help bubbles” 20 | 21 | ## Hold a Sprint Planning Meeting 22 | 23 | ![](../../images/36-sprint-planning-meeting.svg) 24 | 25 | **Attendees**: All Team Members in a Team. The Team Lead acts in the role of “Scrum Master”. 26 | 27 | **Periodicity**: Bi-weekly (every 2 weeks) in the week where the “OKR Check-in Meeting” is NOT held. 28 | 29 | **Duration**: 5-20 minutes per person – or 2 hour maximum for the whole team. 30 | 31 | **Important**: Keep the meeting full of energy and ambition. Don’t speak slowly or go into too much detail unless it’s relevant to others. Everyone should leave the meeting excited – not drained! 32 | 33 | **Purpose**: Have a clean, balanced, exciting, and ambitious plan of significant tasks / to dos for the coming 2 weeks. 34 | 35 | Hold the Sprint Planning Meeting 36 | 37 | - The Team Lead says welcome and reminds everyone that: 38 | - The meeting should be full of energy and ambition – not drain our energy. 39 | - “You get out what you put in”. Work is like any other aspect of life: The more energy and ambition you put into it, the more it will give back. Positivity, energy, excitement are intentional states of mind…. and this meeting is your chance to add that your work life. 40 | - Preparation is key and everyone needs to prepare thoroughly before these meetings: If not, the meetings will be “yada yada” and drain everyone’s energy. 41 | - Everyone takes turns and presents their Sprint Planning. 42 | - Share your screen so you can point at the item you are talking about 43 | - At the end of the meeting, everyone will have visibility into what their Team Members are doing. We will we able to move forward like a Team of Leaders. 44 | 45 | ## Do a Daily Standup 46 | 47 | ![](../../images/37-daily-standup.svg) 48 | 49 | “Daily standups” are – in Scrum/Agile Terminology – a daily meeting in the morning where all Team Members give a short update on 3 key things: 50 | 51 | 1. What have you **accomplished** since last meeting? 52 | 2. What are your **plans** for today? 53 | 3. Is anything **blocking** you? 54 | 55 | Because we value concentration time so much, we’ve decided to skip the Daily Standup meetings – and then use the [#daily-updates](https://interaction-design.slack.com/archives/CPRN9JWHK) channel on Slack instead. 56 | 57 | This will only as long as everyone consistently remembers to submit their updates at the end (or beginning) of their work day. 58 | 59 | ## Prepare for Bi-Weekly OKR 1:1 Check-in Meeting 60 | 61 | ![](../../images/38-one-to-one-checkin-prep.svg) 62 | 63 | All the weeks where there is NOT a Sprint Planning meeting, you hold a “1:1 OKR Check-In” with your Team Lead. 64 | This is your chance to get a good, relationship-building conversation with your Team Lead and to report progress on your OKRs. 65 | This is how you prepare: 66 | 67 | - For each Key Result you own you make an update in our OKR spreadsheet. That way, we all head into our OKR meetings with a fully updated OKR spreadsheet. 68 | - [add more things to do as preparation here, e.g. questions to ask yourself] 69 | 70 | ## Hold the Bi-Weekly Team-wide OKR Check-in Meeting 71 | 72 | ![](../../images/39-team-checkin.svg) 73 | 74 | _Held bi-weekly, i.e. on the weeks where there is NOT a Sprint Planning meeting, right after the 1:1 Check-ins_ 75 | 76 | After the Team Lead has had a round 1:1 OKR check-ins, it’s time for the Team-wide OKR Check-in Meeting. 77 | 78 | This Team-wide meeting could be the day after the 1:1 Meetings or on the same day. Just make sure that you 79 | 80 | If you already have a recurring Team-wide meeting, then hold this “Team-wide OKR Check-in Meeting” at the same time. There’s no reason for having too many meetings. 81 | 82 | At the end of the quarter, it is time to [assess your OKRs](./05-assess-your-okrs). 83 | -------------------------------------------------------------------------------- /guides/onboarding/README.md: -------------------------------------------------------------------------------- 1 | # Onboarding 2 | 3 | Welcome aboard! 4 | 5 | We know you’re amazing because you’re here (otherwise, you wouldn’t be here). 6 | Congrats: You've landed one of the greatest jobs in the world! 🎉 7 | 8 | ![image](https://cdn.shopify.com/s/files/1/2297/6885/collections/plain_no_back_235x235@2x.png) 9 | 10 | Now it’s time to get you up to speed with all the things you need to know 11 | about your role at the IxDF and your day-to-day work as a developer. 12 | 13 | Before you start, please ensure that you know your mentor (onboarding buddy) 14 | to make your onboarding process smooth and easy. 15 | 16 | ## Contribute to our documents 17 | 18 | From here on, you will read a lot of documents in different places. Your first 19 | contribution to IxDF is to help us make those documents as perfect as humanly possible 20 | and your fresh look is invaluable. 21 | We don't expect you to spend too much time and feel pressured, however you can: 22 | 23 | 1. Fix broken links, invalid/obsolete statements, typos, incorrect instructions, etc. 24 | Don't be afraid to commit your changes 🙂 25 | 1. Share your feedback with your onboarding buddy 26 | 27 | ## Plan 28 | 29 | 1. To start, head over to [🔒 IxDF Handbook Course](https://www.interaction-design.org/courses/ixdf-handbook) 30 | and go through Lesson 1 and Lesson 2 where the onboarding is explained. 31 | 1. Set up and know your [collaboration tools](../collaboration-tools.md). 32 | 1. Know our [expectations from you and your work](../roles/senior-developer). 33 | 1. Get closer to coding: Setup your [🔒 working environment](https://github.com/InteractionDesignFoundation/IxDF-web/blob/main/docs/environment/first-run/README.md) 34 | (private repository link) — It’s time-consuming (2-3 hours), so don't wait. 35 | While your tools are being downloaded/installed, you can continue with the list. 36 | 1. Never stop learning 📖. Go through our library and create a plan to acquire 37 | every bit of knowledge there. Once you have a plan, please discuss it with 38 | your mentor. (Are you full-stack? Then please open both links☀): 39 | - Literature/subscriptions [for back-end developers](../../library/backend/literature) 40 | - Literature/subscriptions [for front-end developers](../../library/frontend/literature) 41 | 1. If you have any issues accessing the platform, company culture course 42 | or our collaboration tools, please ping the Member Experience team (`@member-experience-team`) 43 | via Slack (#onboarding-buddy-chat), so they can assist you. By this point, 44 | you should have already completed lesson 0 of the IxDF Onboarding & Company Culture course, 45 | so now you may continue with the rest of the lessons. 46 | 1. Go through our guides: 47 | 1. [Scrum](../../outdated/scrum/README.md) 48 | 1. [🔒 Git Flow](https://github.com/InteractionDesignFoundation/IxDF-web/blob/main/docs/workflows/git-flow.md) 49 | 1. Setup Xdebug 50 | 1. [How to get domain knowledge](onboarding--domain-knowledge.md) 51 | 1. Coding (finally! 🎉) 52 | 1. [🔒 File-naming conventions](https://github.com/InteractionDesignFoundation/IxDF-web/blob/main/docs/code/naming-conventions.md) 53 | 1. [🔒 Contributing standards](https://github.com/InteractionDesignFoundation/IxDF-web/blob/main/CONTRIBUTING.md) 54 | 1. [🔒 Platform glossary](https://github.com/InteractionDesignFoundation/IxDF-web/blob/main/docs/glossary.md) 55 | 1. Architecture (Are you full-stack? You know what to do 😊) 56 | - [🔒 Backend](https://github.com/InteractionDesignFoundation/IxDF-web/blob/main/docs/code/backend/architecture.md) 57 | - [🔒 Frontend](https://github.com/InteractionDesignFoundation/IxDF-web/blob/main/docs/code/frontend/architecture.md) 58 | 1. [🔒 Setup your IDE](https://github.com/InteractionDesignFoundation/IxDF-web/blob/main/docs/environment/IDE/README.md) 59 | for the project. 60 | 61 | Happy reading/hacking! 62 | 63 | ## What’s next? 64 | 65 | Are you ready for new challenges? Great! 66 | 67 | Your onboarding buddy should prepare a number of tasks for your smooth onboarding 68 | to the codebase. You will be assigned to your first GitHub issues, make your first 69 | contribution to our codebase, and create your first PR — a lot of exciting stuff! 70 | 71 | Your first GitHub issues will be tasks that take you through some [core sub-systems](https://docs.information-architecture.org/domain/systems-and-code-owners.html) 72 | of our codebase. That will give you a better overview of what these sub-systems 73 | do and the state of the code within each sub-system (e.g. what’s the amount of 74 | technical debt versus up-to-date code in a given system). Don’t be alarmed if some 75 | of the issues will lead you into areas of the codebase where you find technical-debt 76 | or spaghetti code. That’s intentional, so you get exposed to both great code and technical debt. 77 | 78 | May the Force be with you! 79 | 80 | ## Provide feedback and present your progress 81 | 82 | In a few weeks, you’ll have a chance to look back at your progress within the IxDF. 83 | The entire development team will be very excited to hear your feedback. You'll meet 84 | very often with your onboarding buddy, so you'll have a good opportunity to ask 85 | for directions, and new issues, get answers for your questions, and get feedback. 86 | Here's a list of things you can share with your onboarding buddy or your colleagues: 87 | 88 | - Coding: What have you finished and deployed to production that is now used by hundreds or thousands of people? 89 | - Learning: What is your progress on consuming our library? Do you find them effective? 90 | - Domain: What have you learned about the IxDF and our platform? 91 | How can you help improve the most critical parts of our platform? 92 | - Culture: Can you list our vision, mission, and core values? What can you do to 93 | help IxDF accomplish its audacious goals? 94 | 95 | 🦄 96 | -------------------------------------------------------------------------------- /library/frontend/conventions--js.md: -------------------------------------------------------------------------------- 1 | # IxDF's JavaScript Conventions 2 | 3 | This document extends 4 | [Clean code principles for JavaScript](clean-code-js.md). 5 | 6 | [[toc]] 7 | 8 | ## Browser support 9 | 10 | Support evergreen browsers only, usually all versions released latest 3 years (depends on info from Google Analytics). 11 | 12 | ## Code style 13 | 14 | Our code-styling rules are based on `eslint:recommended` rules. 15 | We also use some ESLint plugins to extend these rules. 16 | You can check all our custom rules at the [.eslintrc.js](https://github.com/InteractionDesignFoundation/IxDF-web/blob/main/.eslintrc.js) file. 17 | 18 | ## Docblocks 19 | 20 | [Use JSDoc](conventions--js) together with type definitions files. 21 | It will help both your IDE and developers to check types. 22 | This provides main benefits from TypeScript, but without translation cost and improved readability. 23 | 24 | Example: 25 | 26 | ```js 27 | // file: userAuthPolicy.js 28 | /** 29 | * @typedef {import('./user.d.ts').User} User 30 | */ 31 | 32 | /** 33 | * @param {User} user 34 | * @returns {boolean} 35 | */ 36 | function isAdmin(user) { 37 | return user.roles.includes('admin'); 38 | } 39 | ``` 40 | 41 | ```ts 42 | // file: user.d.ts 43 | export interface User { 44 | first_name: string; 45 | last_name: string; 46 | email: string; 47 | profil_image_url: string; 48 | roles: string[]; 49 | } 50 | ``` 51 | 52 | ## Explicit type definitions 53 | 54 | Use JSDoc and type checks in code to avoid errors like a null pointer: `TypeError: null is not an object`. 55 | If a variable type described as `@param {HTMLElement} element`, 56 | it should not contain `null` or `undefined` or other types. 57 | If the variable can contain a `null`, please describe it explicitly: `@param {HTMLElement|null} element`. 58 | 59 | ## Variable Names 60 | 61 | 1. Variable names generally shouldn’t be abbreviated. 62 | 1. You SHOULD use camelCase to name variables. 63 | 64 | ## Variable assignment 65 | 66 | Prefer `const` over `let`. Only use `let` to indicate that a variable will be reassigned. Never use `var`. 67 | 68 | ## Strict Comparisons 69 | 70 | Always use a triple equal to do variable comparisons. If you’re unsure of the type, cast it first. 71 | 72 | ```js 73 | // GOOD 74 | const one = 1; 75 | const another = '1'; 76 | 77 | if (one === parseInt(another)) { 78 | // ... 79 | } 80 | ``` 81 | 82 | ## Function keyword vs. arrow functions 83 | 84 | Function declarations should use the function keyword. 85 | 86 | ```js 87 | // GOOD 88 | function scrollTo(offset) { 89 | // ... 90 | } 91 | 92 | // BAD 93 | // Using an arrow function doesn’t provide any benefits here, while the 94 | // `function` keyword immediately makes it clear that this is a function. 95 | const scrollTo = (offset) => { 96 | // ... 97 | }; 98 | ``` 99 | 100 | Terse, single line functions may also use the arrow syntax. There’s no hard rule here. 101 | 102 | ```js 103 | // GOOD 104 | function sum(a, b) { 105 | return a + b; 106 | } 107 | 108 | // It’s a short and simple method, so squashing it to a one-liner is ok. 109 | const sum = (a, b) => a + b; 110 | ``` 111 | 112 | Higher-order functions may use arrow functions if it improves readability. 113 | 114 | ```js 115 | function sum(a, b) { 116 | return a + b; 117 | } 118 | 119 | // GOOD 120 | const adder = (a) => (b) => sum(a, b); 121 | 122 | // OK, but unnecessarily noisy. 123 | function adder(a) { 124 | return function (b) { 125 | return sum(a, b); 126 | }; 127 | } 128 | ``` 129 | 130 | Anonymous functions should use arrow functions (Unless they need access to `this`). 131 | 132 | ```js 133 | ['a', 'b'].map((a) => a.toUpperCase()); 134 | ``` 135 | 136 | ## Object and array destructuring 137 | 138 | Destructuring is preferred over assigning variables to the corresponding keys. 139 | 140 | ```js 141 | // GOOD 142 | const [hours, minutes] = '12:00'.split(':'); 143 | 144 | // BAD, unnecessarily verbose, and requires an extra assignment in this case. 145 | const time = '12:00'.split(':'); 146 | const hours = time[0]; 147 | const minutes = time[1]; 148 | ``` 149 | 150 | Destructuring is precious for passing around configuration-like objects. 151 | 152 | ## Promise 153 | 154 | We actively use `async/await` in our code. 155 | So for promises the recommended approach is to use async/await instead of `Promise.then()`. 156 | The Reason for using async/await is that it’s clean and has an easy-to-read syntax. 157 | 158 | ```js 159 | try { 160 | const response = await promiseToResolve(); 161 | } catch (error) { 162 | log(error); 163 | } 164 | ``` 165 | 166 | Or with our custom fetch promise 167 | 168 | ```js 169 | const response = await getHttpClient() 170 | .get('url') 171 | .catch((error) => log(error)); 172 | if (response) { 173 | notify.success(response.message); 174 | } 175 | ``` 176 | 177 | ## Interacting with the DOM 178 | 179 | Many times we will need to select DOM elements in our JS, there can be multiple approaches for getting the DOM element. 180 | But for consistency and clarity purposes, we SHOULD use data attributes as selectors. 181 | 182 | ```html 183 |
...
184 | ``` 185 | 186 | ```js 187 | const cards = document.querySelectorAll('[data-course-card]'); 188 | ``` 189 | 190 | Unique elements should be selected by their `id` attribute: 191 | 192 | ```html 193 |
...
194 | ``` 195 | 196 | ```js 197 | const subscribeForm = document.getElementById('subscribe-form'); 198 | ``` 199 | 200 | ## Back-end named routes 201 | 202 | Use `@route` annotations/comments to specify Laravel route names. 203 | 204 | Example: `@route 'api.course.enrollment.store'`. 205 | It solves a problem when we change the URL for a route on back-end (where we use named routes) 206 | but forget to change it in JS code (where we may hardcode it). 207 | -------------------------------------------------------------------------------- /library/frontend/literature.md: -------------------------------------------------------------------------------- 1 | # IxDF's literature for front-end developers 2 | 3 | > You are reading this [...] for two reasons. First, you are a programmer. Second, you want to be a better programmer. Good. We need better programmers. 4 | > 5 | > -Robert C. Martin (from Clean Code) 6 | 7 | We have, again and again, experienced that it’s not enough to be a good developer — let alone be a developer. We also have 8 | experienced in our team that once a developer has studied the correct content, the code quality and the collective peace of mind 9 | have multiplied. That’s why we have curated a great deal of material for ourselves to become better. 10 | 11 | In IxDF, it is essential for developers to study the content in our library. This list is not here for a developer to ignore. 12 | An IxDF developer should have read the whole library — **at the least**. 13 | 14 | > The frenetic rate of change in our industry means that software developers must continue to learn copious quantities just to keep up. 15 | > Woe to the architects who stop coding—they will rapidly find themselves irrelevant. Woe to the programmers who stop learning new 16 | > languages—they will watch as the industry passes them by. Woe to the developers who fail to learn new disciplines and techniques—their 17 | > peers will excel as they decline. 18 | > 19 | > -Robert C. Martin (from Clean _Coder_) 20 | 21 | ## Index 22 | 23 | You can find all books and videos on the shared folder `IxDF - Shared Reading - Library of Development literature and videos`. 24 | _Warning for devs having small SSDs:_ The videos may take up more than 10gb on your disk. That’s why 25 | you may want to selectively sync those you want to study into your computer when you want to study them. 26 | 27 | 1. Back-end Foundations 28 | 1. Frontend 29 | 1. Foundations 30 | 1. Subscriptions 31 | 1. Awesome lists 32 | 33 | ## Backend 34 | 35 | Every frontend developer should have some backend knowledge to have basic working skills & collaborate with backend developers. 36 | 37 | ### Foundations 38 | 39 | 1. [Laravel Blade](https://laravel.com/docs/master/blade) - PHP template engine. Frontend developers should understand how to 40 | use `@extend`, `@include`, `@component`, `@section`, `@push`, `@foreach` and `@if` directives. They should also understand when they should use `{{ $variable }}` and `{!! $variable !!}` (display escaped/unescaped data). 41 | 1. How to get an instance of the authenticated Member at the view layer and how to determine whether the visitor is a guest or not (see 42 | [🔒 Authenticated Member instance](https://github.com/InteractionDesignFoundation/IxDF-web/docs/library/backend/hints/authenticated-member-instance.md)). 43 | 1. How to 44 | [🔒 create a new route and a new test view for it](https://github.com/InteractionDesignFoundation/IxDF-web/docs/code/backend/hints/create-test-route.md) for testing purposes. 45 | Sometimes it’s a faster way to implement a new feature. 46 | 47 | For more back-end hints, please see [🔒 backend hints dir](https://github.com/InteractionDesignFoundation/IxDF-web/docs/code/backend/hints). 48 | 49 | ## Frontend 50 | 51 | Every frontend developer should 52 | 53 | - have a basic set of programming skills (Foundations), 54 | - be aware of modern techniques, tools, and APIs (Subscriptions and Awesome lists). 55 | 56 | ### Foundations 57 | 58 | 1. Classic programming skills: [Clean Code: JavaScript](clean-code-js.md): 59 | Software engineering principles, from Robert C. Martin's book Clean Code, adapted for JavaScript. 60 | 1. [Eloquent JavaScript](https://eloquentjavascript.net/) (free ebook) or use pdf version from shared library. 61 | 1. [`Martin Fowler - Refactoring - Improving the Design of Existing Code, 2nd edition`](https://martinfowler.com/books/refactoring.html) (book) or use pdf version from shared library. 62 | 1. Design Patterns (book): 63 | [Addy Osmani - Learning JavaScript Design Patterns - 2017](https://addyosmani.com/resources/essentialjsdesignpatterns/book/) 64 | 1. CSS (book): `Verou L. - CSS Secrets - 2015`. 65 | 1. Topic: BEM CSS methodology: 66 | [MindBEMding](https://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/), 67 | [BEM 101](https://css-tricks.com/bem-101/). 68 | 1. Topic: 69 | [KISS, YAGNI & DRY Principles](https://code.tutsplus.com/tutorials/3-key-software-principles-you-must-understand--net-25161) 70 | 1. Optional: Network (book): [Ilya Grigorik - High Performance Browser Networking](https://hpbn.co/). 71 | 72 | ## Subscriptions 73 | 74 | It’s very useful to subscribe to some weekly newsletters or podcasts and be aware of all the events and news in the front-end world. 75 | 76 | 1. JavaScript Weekly newsletter: [javascriptweekly](https://javascriptweekly.com/issues) 77 | 1. Frontend Focus weekly newsletter: [frontendfoc](https://frontendfoc.us/issues) 78 | 1. YouTube channel: [Google Chrome Developers](https://www.youtube.com/channel/UCnUYZLuoy1rq1aVMwx4aTzw). 79 | 1. Dev Channel by ChromiumDev @medium: 80 | [![RSS](https://www.maldonadonoticias.com/beta/images/headers/rss-icon.gif)](https://medium.com/feed/dev-channel) 81 | https://medium.com/dev-channel 82 | 1. Optional: CSS weekly newsletter: [css-weekly](https://css-weekly.com) 83 | 1. Optional: Inclusive Components: all about designing inclusive web interfaces: 84 | [![RSS](https://www.maldonadonoticias.com/beta/images/headers/rss-icon.gif)](https://inclusive-components.design/rss/) 85 | https://inclusive-components.design/ 86 | 87 | ## Awesome lists 88 | 89 | Awesome lists are great starting points for any material you'd like to find: Documentation, articles, talks, 90 | tools, etc. All of them are community curated and always up to date 🌲. 91 | 92 | 1. [Awesome Javascript](https://github.com/sindresorhus/awesome) - a curated list of awesome javascript lists 93 | 1. [Awesome CSS](https://github.com/sotayamashita/awesome-css) - a curated list of awesome frameworks, style guide and other cool nuggets for the amazing CSS. 94 | 1. [Awesome BEM](https://github.com/getbem/awesome-bem) 95 | 96 | 🦄 97 | -------------------------------------------------------------------------------- /outdated/scrum/README.md: -------------------------------------------------------------------------------- 1 | # Scrum 2 | 3 | According to the official definition, “Scrum is a framework within which people 4 | can address complex adaptive problems, while productively and creatively delivering 5 | products of the highest possible value.”. 6 | 7 | Scrum is a simple, empricial framework which helps us deal with unpredictable, complex problems. 8 | 9 | ![image](https://scrumorg-website-prod.s3.amazonaws.com/drupal/inline-images/2021-01/scrumorg-scrum-framework-3000.png) 10 | 11 | Scrum implements an empirical process where progress is based on observations of reality, not fictitious plans. 12 | 13 | ## The Scrum Framework 14 | 15 | ### Scrum Values 16 | 17 | ![image](https://user-images.githubusercontent.com/77272856/150678447-cafcd33b-23df-4595-8292-e94f79a8edca.png) 18 | 19 | ### Scrum Team 20 | 21 | Small team of people, consists of: 22 | 23 | - **[Scrum Master](https://www.scrum.org/resources/what-is-a-scrum-master)**: TBC 24 | - **[Product Owner](https://www.scrum.org/resources/what-is-a-product-owner)**: TBC 25 | - **[Developers](https://www.scrum.org/resources/what-is-a-scrum-developer)**: TBC 26 | 27 | ### [Scrum Pillars](https://www.scrum.org/resources/blog/three-pillars-empiricism-scrum) 28 | 29 | - **Transparency**: This means presenting the facts as is 30 | - **Inspection** (by the Scrum Team): Check the product, processes, people, and practices and you work. 31 | - **Adaptation**: Continuous improvement base on the result of Inspection 32 | 33 | ### Scrum Events 34 | 35 | The main goal of these events is to create regularity and minimize the need for meetings. 36 | 37 | - **[Sprint](https://www.scrum.org/resources/what-is-a-sprint-in-scrum)**: 38 | It is the heart-beat of scrum, which encompasses all the work necessary to achieve the Product Goal. 39 | It's a fixed-length event of one month or less. 40 | - **[Sprint Planning](https://www.scrum.org/resources/what-is-sprint-planning)**: Initiates the sprint by laying out the work to be done. 41 | - Questions: 42 | - Why is this sprint valuable? 43 | - What can be done this sprint? 44 | - How will the chosen work get done? 45 | - Outcome: Sprint Backlog 46 | - See: Definition of Done 47 | - **[Daily Scrum](https://www.scrum.org/resources/what-is-a-daily-scrum)**: 48 | - Purpose: 49 | - Inspect progress toward Sprint Goal 50 | - Synchronize activities 51 | - Plan for the next 24 hours 52 | - Team members often meet immediately after the Daily Scrum for detailed discussions or replan. 53 | - How: 54 | - It's 15 minutes (timebox) to keep everyone focused 55 | - It happens at the same time & location to reduce complexity 56 | - It happens everyday 57 | - It's by developers and for developers 58 | - It's not a status meeting (update on the tasks they've been working on) 59 | - **[Sprint Review](https://www.scrum.org/resources/what-is-a-sprint-review)**: 60 | - Inspect the outcome of the Sprint & determine future adaptation 61 | - Progress toward Product Goal is discussed with stakeholders 62 | - Maximum of 4-hour timeboxed event for a 4-week Sprint 63 | - See: Backlog Refinement 64 | - **[Sprint Retrospective](https://www.scrum.org/resources/what-is-a-sprint-retrospective)**: 65 | - Inspect individuals, interactions, processes, tools, and their Definition of Done. 66 | - Identify the most helpful changes to improve effectiveness. 67 | - It's timeboxed to a maximum of 3 hours for a 4-week Sprint. 68 | 69 | ### Scrum Artifacts 70 | 71 | Scrum Artifacts enable inspection & adaptation by providing transparency on the work and the value. 72 | 73 | - **[Product Backlog](https://www.scrum.org/resources/what-is-a-product-backlog)**: 74 | - Definition: An emergent, ordered-list of what's needed to improve the product. 75 | - Commitment: Product Goal, which is a future state of the product that helps 76 | Scrum Team to plan their future Sprints. It's either fulfilled or abandoned. 77 | - **[Sprint Backlog](https://www.scrum.org/resources/what-is-a-sprint-backlog)**: 78 | - Definition: 79 | - Sprint Goal (Why) 80 | - Set of Product Backlog Items (What) 81 | - Actionable plan for delivering the Increment (How) 82 | - Commitment: Sprint Goal, which is a single commitment for the sprint. It has 83 | flexibility in terms of the exact work needed to achieve it. 84 | - **[Increment](https://www.scrum.org/resources/what-is-an-increment)**: 85 | - Definition: 86 | - Concrete stepping stone toward the Product Goal. 87 | - Each increment is added to the previous 88 | - All increments should work with each other 89 | - Commitment: Definition of Done, which is a formal description of the minimum 90 | quality required for an increment to be accepted. 91 | 92 | Scrum works not because it has three roles, five events, 93 | and three artifacts, but because it adheres to the underlying 94 | Agile principles of iterative, value-based incremental delivery by frequently gathering 95 | customer feedback and embracing change. 96 | 97 | ### External, introductory resources 98 | 99 | - **[What is Scrum?](https://www.scrum.org/resources/what-is-scrum)**: A short overview of what Scrum is 100 | - **[Scrum Glossary](https://www.scrum.org/resources/scrum-glossary)**: A short Scrum glossary with the most essential terms 101 | - **[Scrum Values](https://kissflow.com/project/agile/how-to-apply-5-scrum-values/)**: Practical examples of applying Scrum Values 102 | 103 | ## More external resources 104 | 105 | - [Sprint planning](https://www.mountaingoatsoftware.com/agile/scrum/meetings/sprint-planning-meeting) 106 | - [Daily scrum](https://www.mountaingoatsoftware.com/agile/scrum/meetings/daily-scrum) 107 | - [Demo/Review meeting](https://www.mountaingoatsoftware.com/agile/scrum/meetings/sprint-review-meeting) 108 | - [Sprint retrospective](https://www.mountaingoatsoftware.com/agile/scrum/meetings/sprint-retrospective) 109 | 110 | ## Scrum in IxDF 111 | 112 | TBC 113 | 114 | 🦄 115 | -------------------------------------------------------------------------------- /guides/onboarding/onboarding--buddyGuide.md: -------------------------------------------------------------------------------- 1 | # Onboarding Buddy 2 | 3 | Every new team-member will be paired with an onboarding buddy to make their onboarding 4 | smooth. The onboarding buddy should work in _almost_ the same timezone as the new team member. 5 | 6 | ## How to be a great Onboarding Buddy 7 | 8 | We have an "Onboarding Buddy playbook" in our shared folder that you should read 9 | and follow in order to create the ultimate onboarding experience for a new team member 10 | (in addition to all the resources on “Onboarding & Company Culture Course” you 11 | should be enrolled to). 12 | 13 | Your main work as an Onboarding Buddy is to help the new team member feel welcome, 14 | not to lose track, and finally get their feedback and transform it into actions like: 15 | 16 | - Update documentation 17 | - Create issues (e.g. `Make dev env works with latest version of XYZ`) 18 | - Make a proposal to optimize the onboarding process 19 | - etc. 20 | 21 | ## Expectations and duties 22 | 23 | It’s not the job of an onboarding buddy to ~teach~, although you might end up doing 24 | a little of that. Your role is to **guide** and inspire with your enthusiasm. 25 | 26 | So while there’s an element of teaching, the skills an onboarding buddy 27 | needs are different to those of a teacher. You need to be an attentive listener, 28 | and you need to have enough practical experience to be able to give your buddy 29 | the right advice at the right time. 30 | 31 | **Set expectations**: Communicate your expectations in a simple and direct manner. 32 | Clarify expected roles, processes and outcomes. 33 | Ensure your buddy understands your expectations and feels motivated to fill them. 34 | 35 | ## Plan 36 | 37 | ### Goals 38 | 39 | Here's a list of things to consider when we try to onboard a new member: 40 | 41 | 1. Make them feel welcome 42 | 1. Make them feel proud of what they do 43 | 1. Connect them to the bigger picture (the WHY) 44 | 1. Let them know why and how much they matter 45 | 1. Try to offload as much information as we can into our shared folders and documents 46 | 1. Make it easy for them to access all necessary information 47 | 1. Simplify the feedback loop (bidirectional) 48 | 49 | ### First day 50 | 51 | 1. Ensure that your buddy has read all onboarding documents. 52 | 1. Ensure that your buddy has all accounts/permissions for our internal and 3rd-party 53 | services (see [Tools and Services checklist](#checklist-for-tools-and-services)). 54 | 1. Ensure that your buddy has [🔒 properly installed developer environment](https://github.com/InteractionDesignFoundation/IxDF-web/blob/main/docs/environment/first-run/README.md). 55 | 1. Arrange end-of-day meetings with your buddy with a specified agenda to get maximum feedback. 56 | The meeting should happen at the end of each day during the first week. 57 | Why: It will help your buddy understand if they are doing what's expected of the 58 | at the right pace and are focused on the correct tasks, as well as receive 59 | clear instructions, advice and constructive criticism to help them improve. 60 | 1. Start changing code: Prepare 3-10 tasks for smooth entry into the project. Examples: 61 | 1. Write tests for feature X (the goal is to introduce feature X, introduce our tools and workflows (GitHub, git, CI)) 62 | 1. Pickup and fix any bug from our automated bug-report systems (Slack, New Relic, Bugsnag, etc.) (goal: introduce tools, fix a bug) 63 | 1. Review a Pull Request (goal: introduce our Pull Request flow and a new piece of code). 64 | 65 | ### First week 66 | 67 | 1. Ensure that your buddy has a plan to read developer and general literature 68 | as well as materials from our shared folders (50/50 mix of general/developer literature). 69 | 1. Ask for a summary feedback for the first week. 70 | 71 | ### First month 72 | 73 | 1. Ensure that you got maximum feedback from your buddy and transformed it into actions. 74 | 75 | ### In a month: finish mentoring 76 | 77 | **Evaluate developer onboarding process**: Now you need to evaluate the onboarding 78 | process to make sure that everything is up to the standard. 79 | 80 | When evaluating the process, simply refer to [our goals](#goals) and answer the 81 | following questions: 82 | 83 | 1. Do we have an effective mentoring program? 84 | 1. What/how can we improve? This includes documents, processes, tools, etc. 85 | 86 | ## Checklist for Tools and Services 87 | 88 | This is a list of tools and services that a new member should have access to. 89 | Dev specific (usually handled by a dev team lead): 90 | 91 | - [GitHub](https://github.com): Source code storage, issue tracker and CI/CD tool. Ensure that the new developer is attached to the `devs` team. 92 | - [Laravel Forge](https://forge.laravel.com/circles/4114/edit): Server Provision service for our servers & sites. Mentee should be added to "Development Team" circle. Ensure 2FA is enabled. 93 | - [PHPStorm license](https://account.jetbrains.com/assets/subscriptions): send an invitation to a corporate gmail account. 94 | - [Downnotifier](https://downnotifier.com/): Set cell phone numbers to subscribe to emergency notifications. 95 | - Optional: [Google Analytics](https://analytics.google.com): Analytics service that tracks and reports website traffic. 96 | - Optional: [Google search console](https://www.google.com/webmasters/tools): Monitor Google Search results data. 97 | - [GTmetrix](https://gtmetrix.com/): Analyze web page's speed performance [👥 shared account]. 98 | - [New Relic](https://newrelic.com/): Log errors and monitor application performance [👥 shared account]. 99 | 100 | Company-wide services (usually handled by a Hiring Process Manager): 101 | 102 | - [Gmail](https://gmail.com): Corporate email box. 103 | - [Slack](https://interaction-design.slack.com): Our main communication tool. Ensure that the new developer is attached to `Developers` slack team/user-group. 104 | - [Dropbox.com](https://sync.com): Cloud service to share materials, literature, media, etc. Ensure that the new developer has access to all directories that they need: designs, literature (both: general and developers), etc. 105 | - [LastPass](https://www.lastpass.com/): Credentials management tool: store and share credentials. 106 | - [Figma](https://figma.com/): Share designs and assets between designers and developers. 107 | 108 | 🦄 109 | -------------------------------------------------------------------------------- /images/agile-sprints.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /guides/OKR/03-create-your-okrs.md: -------------------------------------------------------------------------------- 1 | # Create Your OKRs 2 | 3 | Once you know [about OKRs](./00-why-okrs), about the IxDF's [OKR cadence](./01-okr-cadence) and our [cascading OKR's](./02-cascading-okrs), you are ready to begin creating your own OKR's. 4 | 5 | ## Familiarize yourself with the OKR Planning Spreadsheet 6 | 7 | 1. Please familiarize yourself with the spreadsheet called “IxDF OKR Planning.xlsx”, which you will find in the folder [IxDF / IxDF - PeopleAndCulture - Job Roles and Organizational Structure](https://www.dropbox.com/home/IxDF%20-%20PeopleAndCulture%20-%20Job%20Roles%20and%20Organizational%20Structure) on our DropBox instance—Available only to IxDF team members. 8 | 2. Study some examples of Objectives, Key Results, and how we measure them really closely. 9 | 3. Read all the “help bubbles” that explain the contents of the cells. 10 | 4. Don’t worry if you don’t fully understand what’s going on when you read the spreadsheet. We’ll explain on the next steps. 11 | 12 | After you’re done, proceed to the next step. Now it’s your turn to define Objectives, Key Results, and some KPIs to measure the progress of your Key Results before your Quarterly OKR Planning Meeting. 13 | 14 | ## Fill Out the Spreadsheet Before the Quarterly OKR Meeting 15 | 16 | ![](../../images/27-okr-spreadsheet-part-1.svg) 17 | 18 | What you do next: 19 | 20 | 1. Fill out the relevant part of the next quarter’s tab in the IxDF OKR Spreadsheet 21 | - If you are a Team Lead, then fill out the Team-wide OKRs, and NOT the Personal OKRs for each Team Member. After that, you hold a meeting with the Executive Level before you hold a meeting with your Team. 22 | - If you are a Team Member, then fill out your Personal OKRs, after which you hold a 1:1 meeting with your Team Lead to refine/improve your Personal OKRs and make sure they are aligned with the Team’s. 23 | 2. Now you’re prepared to hold the Quarterly OKR Meeting, which is the next step in the process. 24 | 3. If you are a Team Lead you FIRST hold a Quarterly OKR Meeting with the Executive Level to get their feedback and approval. THEN, you hold a Quarterly OKR Meeting with your Team. 25 | 26 | ## Define Your Objectives 27 | 28 | ![](../../images/28-okr-spreadsheet-part-2.svg) 29 | 30 | Now, write down your Personal – or your Team’s Objectives. If you’re a Team Lead, you write down your Team’s Objectives. If you’re a Team Member, you write down your Personal Objectives . 31 | 32 | 1. What are the most important impact(s) that I – or my Team – need to make in the coming quarter? 33 | - If you are defining Personal Objectives, then based it on my Team’s Objectives for this quarter 34 | - If you are a Team Lead defining your Team’s Objectives, then base it on the IxDF-wide Objectives) 35 | 36 | Spend some time brainstorming ideas on sticky notes – while doing deep concentration. Group similar ideas together. From there, distill your ideas down into 3 to 5 aspirational Objectives. 37 | 38 | Objectives should be high-level, qualitative statements that are aspirational – not tasks or granular outcomes. 39 | 40 | Please refer to the examples you just read in the “OKR Planning Spreadsheet” 41 | 42 | ## Define Your Key Results 43 | 44 | ![](../../images/29-okr-spreadsheet-part-3.svg) 45 | 46 | Define your Key Results for each Objective 47 | 48 | - How do you measure progress toward a qualitative goal that is inherently un-measurable? You identify measurable outcomes that indicate you’ve achieved your Objective! 49 | - Many people struggle to set Key Results for a qualitative goal. Often they think that qualitative Objectives are unmeasurable. However, by focusing on outcomes it becomes easier. 50 | - Now, for each Objective that you just defined, think about the results you would see (and can measure) if you reached that objective. Again, these are not tasks or to-dos. These are outcomes/results. 51 | - Wrong: “Ship feature X by the end of the quarter.” Right: “Shipping feature X increases new user sign-ups by 10% this quarter.” 52 | - Wrong: “Improve customer experience by the end of the quarter.” Right: “Lower customer service calls by X by end of quarter.” 53 | - If you are the Team Lead: 54 | - Assign each Key Result an Owner on the Team. If a Key Result requires collaboration with another Team, great! The Owner should follow up with them afterwards and make sure they’re on board. 55 | 56 | Please refer to the examples you just read in the “OKR Planning Spreadsheet”. 57 | 58 | ## Define Your KPIs 59 | 60 | ![](../../images/30-okr-spreadsheet-part-4.svg) 61 | 62 | A KPI (Key Performance Indicator) is a metric used to measure something, i.e. it’s an “indicator of performance”. Here’s an example: 63 | 64 | - **Objective 1**: Become the most popular bootcamp in UX 65 | - **Key Result 1 for Objective 1**: Double the amount of sign-ups from 50 to 100 students per cohort. 66 | - **KPI for Key Result 1**: Number of Students per cohort 67 | 68 | As mentioned, the KPI for the Key Result 1 would be “Number of Students per cohort” and you would be able to publish a direct link to the NOVA Bootcamp Control Panel where you can read the always-updated value of that KPI, which may currently be 73 students per cohort. 69 | 70 | KPIs are superb (and fun!) ways to measure exact progress. Whenever possible, use KPIs to measure your progress. 71 | 72 | ![](../../images/22-okr-checklist.svg) 73 | 74 | ## Ramp Up Your Ambition 75 | 76 | ![](../../images/31-okr-spreadsheet-part-5.svg) 77 | 78 | Are you done defining your Objectives and Key Results? Great! Then it’s time to give them one more iteration! 79 | 80 | Please do the following: 81 | 82 | 1. Review the Objectives and Key Results you’ve defined and ask whether they’re ambitious enough. If you feel totally confident, you can hit a Key Result, increase the target by approximately 30% and then create a plan mapping out how you will achieve it. If you’re not at all sure you’ll hit a Key Result target, it’s probably set just right. 83 | 2. Make sure the Key Results are articulated well and detailed. You want to be able to score them later on a percentage scale. 84 | 3. Go to the next step about “S.M.A.R.T” and use that as a checklist (see the next step). 85 | 4. Lastly, consider whether you have too many or too few Objectives and Key Results. 86 | 87 | ## Ensure Your OKRs are S.M.A.R.T 88 | 89 | ![](../../images/33-smart-okrs.svg) 90 | 91 | ## Hold a Quarterly OKR Meeting 92 | 93 | ![](../../images/34-quarterly-meeting.svg) 94 | 95 | The Quarterly OKR Planning Meeting 96 | 97 | - The Team Lead makes a new entry for a new quarter for their team by creating a new section in the first tab of the spreadsheet “IxDF OKR Planning.xlsx” 98 | - The Team Lead closely studies the IxDF-wide Objectives 99 | - The Team Lead takes a call with the IxDF Executive Level and asks questions. The better aligned we are, the smoother everything goes. 100 | - The Team Lead fills out all OKRs for their team as best as possible. 101 | - This is a concentration-demanding and lengthy process. It requires strategic overview, long-term thinking, and the ability to constantly switch mindset from “strategic, high-level, long-term thinking” to “concrete execution-level work”. 102 | - Expect this to take up to a full day of high-concentration work – perhaps spread out over several days if your brain starts to burn. 103 | - The Team Lead meets with the Executive Level to verify and refine the Team’s OKRs. 104 | - The Team Lead then meets with their Team where the Team Lead presents the plan for the next quarter. 105 | - Each Team Member then develops Personal OKRs based on the Team’s OKRs. 106 | - Each Team Member meets 1:1 with the Team Lead to verify and refined their Personal OKRs. 107 | 108 | With your OKR's created, it is time to execute on them for the next six weeks, but to do so effectively, 109 | you will need to [stay aligned as a team](./04-stay-aligned-as-a-team). 110 | -------------------------------------------------------------------------------- /images/continuous-delivery.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /library/frontend/conventions--jsdoc.md: -------------------------------------------------------------------------------- 1 | # IxDF's JSDoc Conventions 2 | 3 | For JavaScript code documentation, we use [JSDoc blocks](http://usejsdoc.org/). 4 | There are a few type declarations standards in the JS ecosystem, namely: 5 | 6 | - [JSDoc](https://jsdoc.app/) 7 | - [Google Closure Compiler](https://github.com/google/closure-compiler/wiki/Types-in-the-Closure-Type-System) 8 | - [TypeScript](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html) 9 | 10 | We use the most compatible and least confusing options from all of them. 11 | Most likely, your IDE and tools we use also support all of them. 12 | This document is created to avoid confusion and increase consistency. 13 | 14 | --- 15 | 16 | [[toc]] 17 | 18 | ## JSDoc vs. PHPDoc 19 | 20 | Comparing with [PHPDoc](./../backend/conventions--php#docblocks), there are some differences: 21 | 22 | 1. JSDoc uses`@returns` instead of `@return`; 23 | 2. Curly brackets are used as wrappers for variable types, e.g., `{Object}`, `{Array}`. 24 | 3. `{number}` is used instead of `integer` and `float` in PHPDoc. 25 | 26 | A good example of using JSDoc: 27 | 28 | ```js 29 | /** 30 | * Sends logging information to server. 31 | * 32 | * @param {string} errorMessage Message to send. 33 | * @param {string} [fileName] Name of the file where the logging event was discovered 34 | * @param {Object} [postedData = {}] POST body data, provides some context of the logging event (optional with default value). 35 | * @returns {boolean} Whether it was sent. 36 | */ 37 | function logError(errorMessage, fileName, postedData = {}) { 38 | // some code 39 | } 40 | ``` 41 | 42 | ## Tags 43 | 44 | The most used JSDoc block tags: 45 | 46 | - [@param](http://usejsdoc.org/tags-param.html) for describing function parameters. 47 | - [@returns](http://usejsdoc.org/tags-returns.html) for describing the return type of functions. 48 | - [@type](http://usejsdoc.org/tags-type.html) to specify the type of variable. 49 | - [@typedef](http://usejsdoc.org/tags-typedef.html) to define a data structure. 50 | 51 | ## Types 52 | 53 | ### Scalars 54 | 55 | Use lowercase notation: 56 | 57 | ```js 58 | /** @type {string} */ 59 | /** @type {number} */ 60 | /** @type {function} */ 61 | ``` 62 | 63 | ### Nullable types 64 | 65 | ```js 66 | // Nullable 67 | /** @param {?string} userName */ 68 | /** @param {?HTMLElement} element */ 69 | 70 | // Also nullable (using Type Union syntax) 71 | /** @param {string|null} userName */ 72 | /** @param {HTMLElement|null} element */ 73 | 74 | // Not nullable (we don't use this syntax: all types are not nullable by default (except null) according to our conventions) 75 | /** @param {!string} userName */ 76 | /** @param {!HTMLElement} element */ 77 | ``` 78 | 79 | ::: info 80 | Whether a type is nullable or not nullable by default? - **Not nullable**! 81 | 82 | There is confusion around this, both TypeScript and Closure compiler treat scalars as not nullables by default, 83 | but Closure treats Instance Types as nullable (TypeScript doesn’t). 84 | We have chosen the TypeScript way here. 85 | ::: 86 | 87 | ### Optional parameters 88 | 89 | ```js 90 | // The most conventional and widely recognized. The square brackets denote that the parameter is optional. 91 | /** @param {string} [userName] */ 92 | 93 | // Optional with default value 94 | /** @param {string} [userName='Unknown'] */ 95 | 96 | // Also optional. Used in Google Closure Compiler (understood by most JSDoc parsers but is less commonly used) 97 | /** @param {string=} userName */ 98 | ``` 99 | 100 | ### Type Union 101 | 102 | ```js 103 | /** @type {(number|boolean)} */ 104 | /** @type {function(string|number):(string|number)} */ 105 | ``` 106 | 107 | ### Function type 108 | 109 | ```js 110 | /** @type {function()} */ 111 | /** @type {function(): number} */ 112 | /** @type {function(string, number): number} */ 113 | /** @type {function(string, ...number): number} */ 114 | /** @type {function(?string=, number=): number} */ 115 | ``` 116 | 117 | ### Generics 118 | 119 | ```js 120 | /** 121 | * Standard JS objects: 122 | * @type {Promise} 123 | * @type {Array} 124 | * @type {Array} 125 | * @type {Set} 126 | * @type {WeakMap} 127 | */ 128 | 129 | /** 130 | * Custom generic: 131 | * @template T 132 | * @param {T} thing 133 | * @returns {Array} 134 | */ 135 | export function wrapByArray(thing) { 136 | return [thing]; 137 | } 138 | ``` 139 | 140 | Note, we use TypeScript/Closure notation for generics: `{Array}`. 141 | We do not use the traditional JSDoc syntax: `{Array.}` (the dot is the only difference). 142 | 143 | [More about Generics in Google Closure compiler](https://github.com/google/closure-compiler/wiki/Generic-Types). 144 | 145 | ### Custom types 146 | 147 | #### @typedef tag 148 | 149 | You can specify your custom structure using **typedef** tag: 150 | 151 | ```js 152 | /** 153 | * @typedef {Object} User 154 | * @property {string} name 155 | * @property {string} email 156 | * @property {string|null} phone 157 | */ 158 | 159 | /** 160 | * Or shorthand version: 161 | * @typedef {{name: string, email: string, phone: string|null}} User 162 | */ 163 | 164 | /** 165 | * @param {User} user 166 | */ 167 | function isAdmin(User) { 168 | // 169 | } 170 | ``` 171 | 172 | This is suitable for cases when you are going to use this type within the same file only. 173 | 174 | #### Type Definition Files 175 | 176 | For types used in different files, the preferable option is to use TypeScript syntax 177 | and extract the type definition into a separate `.d.ts` file. 178 | Then you can import this type using JSDoc: 179 | 180 | ```js 181 | /** 182 | * @typedef {import('./user.d.ts').User} User 183 | */ 184 | ``` 185 | 186 | ### Destructured parameters 187 | 188 | **Flat Structures**: document each property on its own line: 189 | 190 | ```js 191 | /** 192 | * @param {Object} user 193 | * @param {string} user.name - The name property. 194 | * @param {?string} user.phone - The phone property, which is nullable. 195 | */ 196 | function logUser({name, phone}) { 197 | // 198 | } 199 | ``` 200 | 201 | **Nested Structures**: 202 | 203 | ```js 204 | /** 205 | * @param {Object} config - The configuration object. 206 | * @param {string} config.user.name - The user's name. 207 | * @param {?string} config.user.phone - The user's phone number, which is nullable. 208 | * @param {Object} config.settings - The settings object. 209 | * @param {boolean} config.settings.isActive - Indicates if the settings are active. 210 | */ 211 | function initialize({ 212 | config: { 213 | user: {name, phone}, 214 | settings: {isActive}, 215 | }, 216 | }) { 217 | // function body 218 | } 219 | ``` 220 | 221 | **Clarity and Conciseness**: Avoid overly complex structures in function parameters. 222 | If a function accepts numerous or deeply nested parameters, 223 | consider refactoring the function or using a type definition to simplify the documentation and enhance code readability. 224 | 225 | ### Advanced TypeScript types and expressions 226 | 227 | ```js 228 | /** 229 | * Takes any union type and excludes `null` 230 | * @template T 231 | * @param {T} thing 232 | * @returns {Exclude} 233 | */ 234 | export function assertNonNull(thing) { 235 | if (thing === null) { 236 | throw new Error('Unexpected null.'); 237 | } 238 | return thing; 239 | } 240 | 241 | // or the same 242 | 243 | /** 244 | * Takes any union type and excludes `null` 245 | * @template T 246 | * @param {T} thing 247 | * @returns {NonNullable} 248 | */ 249 | export function assertNonNull(thing) { 250 | if (thing === null) { 251 | throw new Error('Unexpected null.'); 252 | } 253 | return thing; 254 | } 255 | ``` 256 | 257 | ## References 258 | 259 | - [JSDoc Cheatsheet](https://devhints.io/jsdoc). 260 | - [JSDoc Cheatsheet for TypeScript users](https://docs.joshuatz.com/cheatsheets/js/jsdoc/). 261 | - [Types in the Closure Type System](https://github.com/google/closure-compiler/wiki/Types-in-the-Closure-Type-System). 262 | - [Overview](https://www.jetbrains.com/webstorm/help/creating-jsdoc-comments.html) for using JSDoc PHPStorm and 263 | WebStorm. 264 | -------------------------------------------------------------------------------- /public/images/hydrogenlogo.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /library/frontend/conventions--vuejs.md: -------------------------------------------------------------------------------- 1 | # IxDF's Vue.js conventions 2 | 3 | These conventions are based on the official [Vue.js style guide](https://vuejs.org/style-guide/). Where a choice is given 4 | between various options, this document will explicitly state which one to pick within the IxDF codebases. 5 | 6 | [[toc]] 7 | 8 | ## Use multi-word component names 9 | 10 | User component names should always be multi-word, except for root App components. 11 | This prevents conflicts with existing and future HTML elements, since all HTML elements are a single word. 12 | 13 | **Bad** 14 | 15 | ```html 16 | 17 | ``` 18 | 19 | **Good** 20 | 21 | ```html 22 | 23 | ``` 24 | 25 | ## Always add detailed prop definitions 26 | 27 | Prop definitions should always be as detailed as possible. 28 | 29 | **Bad** 30 | 31 | ```js 32 | const props = defineProps(['status']); 33 | ``` 34 | 35 | **Good** 36 | 37 | ```js 38 | // With TypeScript (recommended) 39 | const props = defineProps<{ 40 | status: string 41 | }>() 42 | 43 | // Without TypeScript 44 | const props = defineProps({ 45 | status: { 46 | type: String, 47 | required: true, 48 | } 49 | }) 50 | ``` 51 | 52 | ## Add a key when using `v-for` 53 | 54 | A key with v-for is always required on components, in order to maintain internal component state down the subtree. 55 | 56 | **Bad** 57 | 58 | ```html 59 |
    60 |
  • {{ todo.text }}
  • 61 |
62 | ``` 63 | 64 | **Good** 65 | 66 | ```html 67 |
    68 |
  • {{ todo.text }}
  • 69 |
70 | ``` 71 | 72 | ## Don't use `v-if` with `v-for` 73 | 74 | Never use v-if on the same element as v-for. 75 | 76 | **Bad** 77 | 78 | ```html 79 |
    80 |
  • {{ user.name }}
  • 81 |
82 | ``` 83 | 84 | **Good** 85 | 86 | ```html 87 |
    88 | 91 |
92 | ``` 93 | 94 | ## Component files should be named with PascalCase 95 | 96 | **Bad** 97 | 98 | ``` 99 | components/ 100 | |- mycomponent.vue 101 | |- myComponent.vue 102 | ``` 103 | 104 | **Good** 105 | 106 | ``` 107 | |- MyComponent.vue 108 | ``` 109 | 110 | ## Append "Base" prefix to any foundational components 111 | 112 | Foundational components, such as buttons, tables or icons that get used within more specific components should all begin with the 'Base' prefix. 113 | This ensures they don't clash with HTML element names and also ensures that they are neatly organized together in the codebase. 114 | 115 | **Bad** 116 | 117 | ``` 118 | components/ 119 | |- Button.vue 120 | |- Table.vue 121 | |- Icon.vue 122 | ``` 123 | 124 | **Good** 125 | 126 | ``` 127 | components/ 128 | |- BaseButton.vue 129 | |- BaseTable.vue 130 | |- BaseIcon.vue 131 | ``` 132 | 133 | ## Tightly coupled component names 134 | 135 | Child components that are tightly coupled with their parent should include the parent component name as a prefix. 136 | 137 | If a component only makes sense in the context of a single parent component, that relationship should be evident in its name. Since editors typically organize files alphabetically, this also keeps these related files next to each other. 138 | 139 | **Bad** 140 | 141 | ``` 142 | components/ 143 | |- TodoList.vue 144 | |- TodoItem.vue 145 | |- TodoButton.vue 146 | ``` 147 | 148 | ``` 149 | components/ 150 | |- SearchSidebar.vue 151 | |- NavigationForSearchSidebar.vue 152 | ``` 153 | 154 | **Good** 155 | 156 | ``` 157 | components/ 158 | |- TodoList.vue 159 | |- TodoListItem.vue 160 | |- TodoListItemButton.vue 161 | ``` 162 | 163 | ``` 164 | components/ 165 | |- SearchSidebar.vue 166 | |- SearchSidebarNavigation.vue 167 | ``` 168 | 169 | ## Order of words in component names 170 | 171 | Component names should start with the highest-level (often most general) words and end with descriptive modifying words. This helps make searching for specific components easier and keeps the codebase neatly organised. 172 | 173 | **Bad** 174 | 175 | ``` 176 | components/ 177 | |- ClearSearchButton.vue 178 | |- ExcludeFromSearchInput.vue 179 | |- LaunchOnStartupCheckbox.vue 180 | |- RunSearchButton.vue 181 | |- SearchInput.vue 182 | |- TermsCheckbox.vue 183 | ``` 184 | 185 | **Good** 186 | 187 | ``` 188 | components/ 189 | |- SearchButtonClear.vue 190 | |- SearchButtonRun.vue 191 | |- SearchInputQuery.vue 192 | |- SearchInputExcludeGlob.vue 193 | |- SettingsCheckboxTerms.vue 194 | |- SettingsCheckboxLaunchOnStartup.vue 195 | ``` 196 | 197 | ## Component Name Casing 198 | 199 | Components should always be PascalCase in both .vue and .js files. This has a few advantages over kebab-case: 200 | 201 | - Editors can autocomplete component names in templates, because PascalCase is also used in JavaScript. 202 | - `` is more visually distinct from a single-word HTML element than ``, because there are two character differences (the two capitals), rather than just one (a hyphen). 203 | - If you use any non-Vue custom elements in your templates, such as a web component, PascalCase ensures that your Vue components remain distinctly visible. 204 | 205 | **Bad** 206 | 207 | ```html 208 | 209 | ``` 210 | 211 | **Good** 212 | 213 | ```html 214 | 215 | ``` 216 | 217 | ## Full-word component names 218 | 219 | Don't use abbreviations in component names. 220 | 221 | **Bad** 222 | 223 | ``` 224 | components/ 225 | |- SdSettings.vue 226 | |- UProfOpts.vue 227 | ``` 228 | 229 | **Good** 230 | 231 | ``` 232 | components/ 233 | |- StudentDashboardSettings.vue 234 | |- UserProfileOptions.vue 235 | ``` 236 | 237 | ## Prop name casing 238 | 239 | Always use camelCase for prop declarations and within templates 240 | 241 | ```js 242 | const props = defineProps({ 243 | greetingText: String, 244 | }); 245 | ``` 246 | 247 | ```html 248 | 249 | ``` 250 | 251 | ## Multi-attribute elements 252 | 253 | Elements with multiple attributes should span multiple lines, with one attribute per line. 254 | 255 | **Bad** 256 | 257 | ```html 258 | Vue Logo 259 | ``` 260 | 261 | **Good** 262 | 263 | ```html 264 | Vue Logo 265 | 266 | 267 | ``` 268 | 269 | ## Simple expressions in templates 270 | 271 | Component templates should only include simple expressions, with more complex expressions refactored into computed properties or methods. 272 | 273 | **Bad** 274 | 275 | ````js 276 | {{ 277 | fullName.split(' ').map((word) => { 278 | return word[0].toUpperCase() + word.slice(1) 279 | }).join```(' ') 280 | }} 281 | ```` 282 | 283 | **Good** 284 | 285 | ```js 286 | 287 | {{ normalizedFullName }} 288 | 289 | // The complex expression has been moved to a computed property 290 | const normalizedFullName = computed(() => 291 | fullName.value 292 | .split(' ') 293 | .map((word) => word[0].toUpperCase() + word.slice(1)) 294 | .join(' ') 295 | ) 296 | ``` 297 | 298 | ## Simple computed properties 299 | 300 | Complex computed properties should be split into as many simpler properties as possible. 301 | 302 | **Bad** 303 | 304 | ```js 305 | const price = computed(() => { 306 | const basePrice = manufactureCost.value / (1 - profitMargin.value); 307 | return basePrice - basePrice * (discountPercent.value || 0); 308 | }); 309 | ``` 310 | 311 | **Good** 312 | 313 | ```js 314 | const basePrice = computed(() => manufactureCost.value / (1 - profitMargin.value)); 315 | 316 | const discount = computed(() => basePrice.value * (discountPercent.value || 0)); 317 | 318 | const finalPrice = computed(() => basePrice.value - discount.value); 319 | ``` 320 | 321 | ## Quoted attribute values 322 | 323 | Non-empty HTML attribute values should always be inside quotes. 324 | 325 | **Bad** 326 | 327 | ```html 328 | 329 | ``` 330 | 331 | **Good** 332 | 333 | ```html 334 | 335 | ``` 336 | 337 | ## Directive shorthands 338 | 339 | Within the IxDF codebases, directive shorthands (`:` for `v-bind:`, `@` for `v-on:` and `#` for `v-slot`) should **always** be used. The rule is to either always use directive shorthands, or never - don't mix and match. We've chosen to use them. 340 | 341 | **Bad** 342 | 343 | ```html 344 | 345 | 346 | 347 | 348 | 351 | 352 | 355 | ``` 356 | 357 | **Good** 358 | 359 | ```html 360 | 361 | 362 | 363 | 364 | 367 | 368 | 371 | ``` 372 | 373 | ## Single-file component top-level element order 374 | 375 | Single-File Components should always order ` 385 | 388 | ``` 389 | 390 | **Good** 391 | 392 | ```html 393 | 394 | 397 | 398 | 401 | ``` 402 | -------------------------------------------------------------------------------- /outdated/design-products/delivery-process.md: -------------------------------------------------------------------------------- 1 | # Delivery Process 2 | 3 | This is the process we use to turn product designs into actual products. 4 | 5 | ## Agile Teams 6 | 7 | ![](../../images/agile-teams.svg) 8 | 9 | ### Agile Team Members 10 | 11 | - Member Experience 12 | - Growth 13 | - Development 14 | - Editorial 15 | - Video 16 | - Product Owner 17 | - Design 18 | 19 | ## Agile Organization 20 | 21 | ![](../../images/agile-organization.svg) 22 | 23 | Leverage **epics**, **milestones**, **issues** and **labels** to manage execution of tasks. 24 | 25 | ### Epics 26 | 27 | **Epics** are high level product requirements and/or features requests that require multiple issues to achieve. Epics 28 | may extend into multiple milestones “sprints” or continue indefinitely for iterative improvements (e.g. accessibility 29 | improvements). 30 | 31 | ### Milestones (Sprints) 32 | 33 | ![](../../images/agile-sprints.svg) 34 | 35 | **Milestones** are bi-weekly “fort-nightly” sprints that are two weeks in duration. Milestone consists of multiple 36 | issues that will be addressed in a given sprint. 37 | 38 | - **Now**: Design related tasks for this sprint. 39 | - **Next**: Design related tasks for the next sprint. 40 | - **Later**: Design related tasks for a later sprint. 41 | 42 | **Please Note**: Alternative naming conventions for milestones include a **numeric** (#01, #02, #03) or **date** ( 43 | DD-MM-YYYY) approaches. 44 | 45 | ### Scrum Board 46 | 47 | ![](../../images/scrum-board.svg) 48 | 49 | **Scrum** is an iterative way of working that focuses on breaking down big projects into small, manageable sprints, with 50 | an emphasis on communication and teamwork — and the scrum board embodies this. This board sits at the center of 51 | everything the team does. It shows how far along they are in the sprint, as well as the overall project. 52 | 53 | - **Backlog**: A full list of issues (edits, features, bugs). 54 | - **To Do**: Issues that will be tackled during the milestone “sprint.” 55 | - **In-Progress**: Issues currently being worked on. 56 | - **In-Review**: Issues ready for review or blocked. 57 | - **Done**: Issues that have been completed. 58 | 59 | ### Issues 60 | 61 | ![](../../images/issue-types.svg) 62 | 63 | **Issues** are tasks, design requests, new features or bugs that will be addressed in each milestone. 64 | 65 | #### GitHub Issue Types 66 | 67 | - Design Request: Design a landing page. 68 | - Bug Report: Fix broken cta button. 69 | - Feature or Idea: Add note taking feature. 70 | - Design Edit: Make the logo bigger. 71 | 72 | #### How to Create a GitHub Issue? 73 | 74 | - Issue added to GitHub by a team member. The team member will then assign the appropriate colleague(s) and the issue is 75 | automatically added to the backlog. 76 | - Label added to issue (e.g. `urgency:3`). 77 | - Issue(s) will be assigned by the appropriate Epic by the team member assigned. 78 | - Issue(s) will then be placed in a Milestone based on priority during sprint planning. 79 | 80 | ### Labels 81 | 82 | **Labels** are assigned tags that help organize individual issues (e.g. design request, bootcamp, bug) and indicate the 83 | level of priority (e.g. low, medium, high). 84 | 85 | ## Agile Software 86 | 87 | ![](../../images/agile-software.svg) 88 | 89 | ### GitHub 90 | 91 | **GitHub** as a way to manage execution of tasks (how, when, what). 92 | 93 | - Leverage GitHub to track progress of tasks. 94 | 95 | ### AirTable 96 | 97 | **AirTable** to display roadmap, discovery, and gather user research and feedback from the MEx team. 98 | 99 | - Leverage Gantt View to display high-level roadmap. 100 | - Leverage individual records to gather user feedback and research. 101 | 102 | ### Docs 103 | 104 | **Docs** for notes and documentation (e.g. this document). 105 | 106 | ### Slack 107 | 108 | **Slack** for communication and updates. MIRO for collaboration and ideation sessions. 109 | 110 | ## Delivery Criteria 111 | 112 | ![](../../images/delivery-criteria.svg) 113 | 114 | ### How to Determine Priority? 115 | 116 | Use **Delivery Criteria** to determine priority of issues. The criteria include the **C.H.I.M.E. Metric** of 117 | Maintainability, Impact, Confidence and Ease. 118 | 119 | - **Confidence**: How confident are you in these estimates? 120 | - **Hypothesis**: What do you think is the ROI on this feature? 121 | - **Impact**: How much will this feature impact our members? 122 | - **Maintainability**: How easy is this to maintain over the long-term? 123 | - **Ease/Effort**: What is the development time investment for this feature? 124 | 125 | ## Design Decisions 126 | 127 | How to Make Design Decisions? In order to create the best possible user experience, you should leverage best practices 128 | to help make decisions. We should ask ourselves; **does it violate any of 129 | our [Design Principles](/outdated/design-products/design-principles.md)**? 130 | 131 | **If not, then proceed** :) 132 | 133 | ## Discovery and Delivery Sprints 134 | 135 | ![](../../images/continuous-delivery.svg) 136 | 137 | ### Discovery: AirTable 138 | 139 | - Christian comes up with an idea for electric shock-enabled education and adds it to AirTable as a record that is labeled as an **idea**. 140 | - Christian Mentions the appropriate team members in an AirTable discussion. 141 | - Before the next Quarterly/Team OKR. 142 | - Team member discussion ensues. 143 | - Voting may happen, possibly against **delivery criteria**. 144 | - **Delivery criteria** will determine if the idea is placed in the roadmap. (e.g., does it align with an **Annual/IxDF OKR**? Does it violate our **IxDF design principles**? **M.I.C.E. Score**? **Practical Idealism**?) 145 | - In the next **Quarterly/Team OKR** meeting, If the idea meets the **delivery criteria**, it is added to the roadmap. 146 | - Assigned to the appropriate team(s). 147 | - Example: Design and Development team collaborate on new electric shock-enabled feature. 148 | - Example: Video, Editorial and Growth teams collaborate on a course promo video. 149 | - KR’s are defined for it, which could include: 150 | - Attributes (e.g. feature should have x, y, z) 151 | - Adoption (e.g., x number of users by 21Q4) 152 | - Dates (e.g., launch feature by 21Q3) 153 | 154 | ### Delivery: GitHub 155 | 156 | - Create related GitHub epic with associated issues. 157 | - Team members assigned, requirements explained, added to milestone (See Sprint Planning Process). 158 | - Insert design and/or dev issue template link here. 159 | 160 | ## Design Meetings 161 | 162 | If helpful, you may use these meetings as a guide for your team. 163 | 164 | - **Daily Standup**: 165 | - Daily / Monday–Friday / Via Slack 166 | - Share what you completed today, what you plan on completing tomorrow, and are there any blockers. 167 | - **Sprint Planning**: 168 | - Bi-Weekly (Fortnightly) / Monday / Via Google Hangouts, Slack or Zoom 169 | - Review backlog, determine priority of issues, provide estimates, check goals (i.e. dependencies, clarifications), confirm consensus. 170 | - **Sprint Retrospective**: 171 | - Bi-Weekly (Fortnightly) / Monday / Via Google Hangouts, Slack or Zoom 172 | - Share what went well, what could be improved, define actionable tasks to improve the next sprint. 173 | - **Backlog Refinement**: 174 | - Bi-Weekly (Fortnightly) / Monday / Independently Prior to Sprint Planning 175 | - Clean up backlog issues, determine priority, make sure issues are in alignment with goals, organize in preparation for planning. 176 | 177 | ## Design Sprint Planning 178 | 179 | If helpful, you may use this sprint planning agenda as a guide for your team. 180 | 181 | 1. Hellos :) 182 | 2. **Team Updates** (i.e. Events, Availability, New Systems, Problems). 183 | 3. Collectively **Review Backlog**. 184 | 1. Review backlog, determine priority of issues, provide estimates, check goals (i.e. dependencies, clarifications), confirm consensus. 185 | 4. **Determine Priority** of Issues. 186 | 1. Determine the importance of each issue, make sure each issue is understood, be sure it aligns with our organization goals, and discuss if all issues are represented (i.e. avoid unanticipated tasks). 187 | 5. **Add the Right Mix** of Issues to the To Do Column. 188 | 1. Reject any unsuitable issues (i.e. redundant, badly defined, too big, team can’t control, etc), move the most likely candidates to the todo column, rank them in priority order. 189 | 6. **Check Estimates** & **Assign Work**. 190 | 1. Review workload, add contingency & reserved time for unanticipated issues, determine if we're using everyone’s strengths, are we too ambitious, is anyone overloaded? 191 | 7. **Check Goals**. 192 | 1. Any assumptions? Dependencies? Clarifications needed? 193 | 2. Ask questions, flag any potential problems. 194 | 3. Articulate the sprint goals for us to commit to. 195 | 8. **Determine** 100% Consensus. 196 | 1. If not, repeat step 3 :) 197 | 198 | ## Helpful Agile Terms 199 | 200 | ![](../../images/helpful-agile-terms.svg) 201 | 202 | Below is a list of helpful agile terms. 203 | 204 | - **Daily Standup**: Share what you completed today, what you plan on completing tomorrow, and are there any blockers. 205 | - **Sprint Planning**: Review backlog, determine priority of issues, provide estimates, check goals (i.e. dependencies, clarifications), confirm consensus. 206 | - **Sprint Retrospective**: Share what went well, what could be improved, define actionable tasks to improve the next sprint. 207 | - **Backlog Refinement**: Clean up backlog issues, determine priority, make sure issues are in alignment with goals, organize in preparation for planning. 208 | - **Blockers**: A blocker is anything that is keeping somebody from performing a specific task. 209 | - **OKR**: The acronym OKR stands for Objectives and Key Results. The OKR is a popular strategy for goal setting within organizations. It is a collaborative goal-setting tool which we can use to realize our vision and mission in the best possible way. 210 | - **Objective**: An Objective is a description of a goal to be achieved in the future. An Objective sets a clear direction and provides motivation. An Objective can be thought of as a destination on a map.. 211 | - **Key Result**: A Key Result is a metric with a starting value and a target value that measures progress towards an Objective. A Key Result is like a signpost with a distance that shows how close you are to your Objective. 212 | - **Task**: A task is a description of the work you’ll do to influence a Key Result. If an Objective is your destination and a Key Result shows the distance to go, a task describes what you’ll do to get there, (take a car, row a boat, etc.). 213 | - **Annual/IxDF OKRs**: Annual meetings between key stakeholders to discuss organizational OKRs (e.g., culture, hiring, product, editorial courses). 214 | - **Quarterly/Team OKRs**: Quarterly meetings between teams leads to determine product priorities (e.g., bootcamp grading feature, IxDF shop). 215 | - **M.I.C.E. Score**: Stands for maintainability, impact, confidence and ease. 216 | - **Maintainability**: How easy is this to maintain over the long-term? 217 | - **Impact**: How much will this feature impact those users? 218 | - **Confidence**: How confident are you in these estimates? 219 | - **Ease**: What is the time investment for this feature? 220 | - **S.M.A.R.T.**: Stands for specific, measurable, achievable, realistic and timely. 221 | - **Discovery**: Product discovery focuses on generating ideas for the backlog. 222 | - **Delivery**: Product delivery focuses on implementing the discovery ideas. 223 | - **Impractical Idealism**: Attempting to achieve an idealistic goal—like bringing design education into all corners of the world—using only idealistic success criteria (e.g., maximum number educated, top quality, low cost). 224 | - **Practical Idealism**: Attempting to achieve an idealistic goal—like bringing design education into all corners of the world—using both idealistic success criteria (e.g., maximum number educated, top quality, low cost) as well as practical criteria (e.g., sustainable growth). 225 | -------------------------------------------------------------------------------- /library/backend/SOLID.md: -------------------------------------------------------------------------------- 1 | # IxDF's SOLID Principles for PHP 2 | 3 | Five agile principles that should guide you every time you write code. 4 | And I’ll show you how to apply them with PHP. 5 | I’ll try to be the most practical as possible, and providing examples for each casuistic. 6 | 7 | 1. **S-RP**: Single Responsibility Principle 8 | 1. **O-CP**: Open Closed Principle 9 | 1. **L-SP**: Liskov Substitution Principle 10 | 1. **I-SP**: Interface Segregation Principle 11 | 1. **D-IP**: Dependency Inversion Principle 12 | 13 | ## Single Responsibility Principle 14 | 15 | > A class should have one, and only one, reason to change. 16 | 17 | **This principle is about actors and high level architecture**. 18 | It specifies that a class (or method) must have a specific purpose, ie, a unique responsibility or a reason to change. 19 | 20 | ### Example 21 | 22 | Imagine that we have an interface for reports like this one: 23 | 24 | ```php 25 | interface Report 26 | { 27 | public function getTitle(); 28 | public function getDate(); 29 | public function getHeaders(); 30 | public function getBody(); 31 | public function toCSV(); 32 | public function toHTML($name); 33 | } 34 | ``` 35 | 36 | This interface has two overlapped responsibilities coexisting here: get data and format it. 37 | What if product owner will ask you to support to formats: XML, JSON, PDF? 38 | 39 | This issue could be solved by using two interfaces: `Report` and `ReportFormatter`. 40 | 41 | ```php 42 | interface Report 43 | { 44 | public function getTitle(); 45 | public function getDate(); 46 | public function getHeaders(); 47 | public function getBody(); 48 | } 49 | 50 | interface ReportFormatter 51 | { 52 | public function format(Report $report); 53 | } 54 | 55 | class HtmlReportFormatter implements ReportFormatter 56 | { 57 | public function format(Report $report) 58 | { 59 | $output = ''; 60 | // ... 61 | 62 | return $output; 63 | } 64 | } 65 | ``` 66 | 67 | ### Conclusion 68 | 69 | This principle is often ignored for reasons of practicality and ease of development, 70 | but if you work on large-scale projects, it’s extremely important to respect the pillars of good OOP design, 71 | or we will lose the battle against complexity. 72 | 73 | ## Open Closed Principle 74 | 75 | > You should be able to extend a classes behavior, without modifying it. 76 | 77 | **This principle is about class design and feature extensions**, it based on delegating responsibility to the class. 78 | If we have actions that depend on the subtype of a class, it is easier to provide that feature in the parent class, 79 | and then the subclasses can (re)implement that feature. 80 | 81 | ### Example 82 | 83 | Let’s see it clearer with the example. 84 | 85 | Imagine we have a Board class that contains Rectangles and can calculate the area of the Rectangles. 86 | 87 | ```php 88 | class Rectangle 89 | { 90 | public $width; 91 | public $height; 92 | } 93 | 94 | class Board 95 | { 96 | public $rectangles = []; 97 | 98 | // ... 99 | 100 | public function calculateArea() 101 | { 102 | $area = 0; 103 | foreach ($this->rectangles as $rectangle) { 104 | $area += $rectangle->width * $rectangle->height; 105 | } 106 | 107 | return $area; 108 | } 109 | } 110 | ``` 111 | 112 | But now, our client needs to add circles to the board. 113 | 114 | We have to make our Board to know about Rectangles and Circles, 115 | but if we would respect OCP, we should not need to touch Board or Rectangle. 116 | We should reuse the existing Board and apply it to Circle. 117 | 118 | ```php 119 | interface Shape 120 | { 121 | public function area(); 122 | } 123 | 124 | class Rectangle implements Shape 125 | { 126 | // ... 127 | 128 | public function area() 129 | { 130 | return $this->width * $this->height; 131 | } 132 | } 133 | 134 | class Circle implements Shape 135 | { 136 | // ... 137 | 138 | public function area() 139 | { 140 | return $this->radius * $this->radius * pi(); 141 | } 142 | } 143 | 144 | class Board 145 | { 146 | public $shapes = []; 147 | 148 | // ... 149 | 150 | public function calculateArea() 151 | { 152 | $area = 0; 153 | foreach ($this->shapes as $shape) { 154 | $area+= $shape->area(); 155 | } 156 | 157 | return $area; 158 | } 159 | } 160 | ``` 161 | 162 | ### Conclusion 163 | 164 | **Abstraction is a key**. In many ways this principle is at the heart of object oriented design. 165 | 166 | This is what [Robert Martin wrote](https://blog.8thlight.com/uncle-bob/2014/05/12/TheOpenClosedPrinciple.html) about OCP: 167 | 168 | > I’ve heard it said that the OCP is wrong, unworkable, impractical, and not for real programmers with real work to do. 169 | > The rise of plugin architectures makes it plain that these views are utter nonsense. 170 | > On the contrary, a strong plugin architecture is likely to be the most important aspect of future software systems. 171 | 172 | ## Liskov Substitution Principle 173 | 174 | > Derived classes must be substitutable for their base classes. 175 | 176 | This principle says that every class that inherit from a parent class, must not replicate functionality already implemented in the parent class. 177 | Then the parent class should be able to be replaced by any of its subclasses in any region of the code. 178 | 179 | In this case, we have our class Rectangle, and now we want to create a class Square that extends from Rectangle. 180 | 181 | ```php 182 | class Rectangle 183 | { 184 | protected int $height; 185 | protected int $width; 186 | 187 | public function setWidth($w) { $this->width = $w; } 188 | public function setHeight($h) { $this->height = $h; } 189 | public function getArea() { return $this->height * $this->width; } 190 | } 191 | 192 | class Square extends Rectangle 193 | { 194 | public function setWidth($w) { $this->width = $w; $this->height = $w; } 195 | public function setHeight($h) { $this->height = $h; $this->width = $h; } 196 | } 197 | ``` 198 | 199 | and we create our function to calculate classes : 200 | 201 | ```php 202 | function areaOfRectangle() { 203 | $rectangle = new Rectangle(); 204 | $rectangle->setWidth(7); 205 | $rectangle->setHeight(3); 206 | $rectangle->getArea(); // 21 207 | } 208 | ``` 209 | 210 | as the LSP says, we should be able to change Rectangle by Square 211 | 212 | ```php 213 | function areaOfRectangle() { 214 | $rectangle = new Square(); 215 | $rectangle->setWidth(7); 216 | $rectangle->setHeight(3); 217 | $rectangle->getArea(); // 9 218 | } 219 | ``` 220 | 221 | Remember what we said: “we must make sure that Square classes are extending the Rectangle without changing their behavior”. But, as you can see, 21 is not equal to 9. 222 | 223 | The solution would be to manage the class inheritance hierarchies correctly, for example by introducing the interface `Quadrilateral`. 224 | 225 | ```php 226 | interface Quadrilateral 227 | { 228 | public function setHeight($h); 229 | public function setWidth($w); 230 | public function getArea(); 231 | } 232 | 233 | class Rectangle implements Quadrilateral {} 234 | 235 | class Square implements Quadrilateral {} 236 | ``` 237 | 238 | ### Conclusion 239 | 240 | Following the Liskov Substitution Principle is a good indicator that you are following a correctly hierarchy schema. 241 | And if you don’t follow it, the unit tests for the superclass would never succeed for the subclasses. 242 | 243 | ## Interface Segregation Principle 244 | 245 | > Make fine grained interfaces that are client specific. 246 | 247 | This principle proposes to divide interfaces so they are more specific. 248 | A class can implement multiple interfaces simultaneously, we shouldn’t force clients to deploy methods unnecessary. 249 | 250 | Let’s think about a digital agency that has workers, so I create the interface Worker 251 | 252 | ```php 253 | interface Worker { 254 | public function takeBreak(); 255 | public function code(); 256 | public function callToClient(); 257 | public function attendMeetings(); 258 | public function getPaid(); 259 | } 260 | ``` 261 | 262 | but for example, if we create the class `Manager` and the class `Developer` we are going to have problems with unused methods: 263 | 264 | ```php 265 | class Manager implements Worker 266 | { 267 | public function code() { return false; } 268 | } 269 | 270 | class Developer implements Worker 271 | { 272 | public function callToClient() { echo $swearWord; } 273 | } 274 | ``` 275 | 276 | Then we should create more interfaces. 277 | 278 | ```php 279 | interface Worker 280 | { 281 | public function takeBreak(); 282 | public function getPaid(); 283 | } 284 | 285 | interface Coder { 286 | public function code(); 287 | } 288 | 289 | interface ClientFacer { 290 | public function callToClient(); 291 | public function attendMeetings(); 292 | } 293 | 294 | class Developer implements Worker, Coder {} 295 | 296 | class Manager implements Worker, ClientFacer {} 297 | ``` 298 | 299 | ### Conclusion 300 | 301 | The conclusion here is simple, we can end up with a "fat" class with multitudes of methods specific to a variety of different features. 302 | A system may become so coupled at multiple levels that it is no longer possible to make a change in one place without necessitating many additional changes. 303 | 304 | ## Dependency Inversion Principle 305 | 306 | > Depend on abstractions, not on concretions. 307 | 308 | This is one the most important SOLID principles if you follow TDD. 309 | It refers to a specific form of decoupling software modules. 310 | So, if a class uses other classes, the initialization of the objects has to come from outside. 311 | 312 | As this principle could be difficult to understand, lets review what the principle states: 313 | 314 | > High level modules should not depend on low-level modules, both should depend on abstractions. 315 | > Abstractions should not depend on details. Details should depend on abstractions. 316 | 317 | Then, this principle inverts the way some people may think about OOP, dictating that both classes and subclasses must depend on the same abstraction. 318 | 319 | In this case, I’m going to use the Worker example that we used in the previous principle. 320 | 321 | We have the Manager class, which is the high level class, and then a class called Worker. 322 | The Manager can make Workers to work. Let’s see a traditional OO implementation: 323 | 324 | ```php 325 | // Bad example 326 | class Worker 327 | { 328 | public function work() {} 329 | } 330 | 331 | class Manager 332 | { 333 | private $worker; 334 | 335 | public function setWorker(Worker $w) 336 | { 337 | $this->worker = $w; 338 | } 339 | 340 | public function manage() 341 | { 342 | $this->worker->work(); 343 | } 344 | } 345 | ``` 346 | 347 | Now, we need to add a new kind of specialized workers, we create a new class SpecializedWorker for this. 348 | 349 | ```php 350 | // Bad example 351 | class SpecializedWorker 352 | { 353 | public function work() {} 354 | } 355 | ``` 356 | 357 | Now see the cons: 358 | 359 | **We have to modify the Manager class, and some of the functionality of the Manager might be affected. 360 | The unit tests should be redone.** 361 | 362 | If we would have follow the D-IP, we wouldn’t have had these problems. 363 | 364 | ```php 365 | // Good example 366 | 367 | interface Employee 368 | { 369 | public function work(); 370 | } 371 | 372 | class Worker implements Employee 373 | { 374 | public function work() {} 375 | } 376 | 377 | class SpecializedWorker implements Employee 378 | { 379 | public function work() {} 380 | } 381 | ``` 382 | 383 | ### Conclusion 384 | 385 | The principle of dependency inversion is critically important for the construction of code that is resilient to change. 386 | 387 | ## Final Thoughts 388 | 389 | Using the SOLID principles implies an increased effort. 390 | It will result in more classes and interfaces to maintain. 391 | More complex but more flexible code. 392 | These principles will make our code better and our life as programmers much easier. 393 | Well designed code is easier for programmers to understand. 394 | A lot of these SOLID principles seem to fall out fairly naturally if you practice TDD (or BDD). 395 | 396 | But remember the KISS (Keep It Simple, Stupid), and DRY (Don’t Repeat Yourself) principles. I believe there are no perfect designs, just trade offs, and the SOLID principles can help you evaluate these and achieve a good balance. 397 | 398 | ## Recommended reading 399 | 400 | - [PrinciplesOfOod by Uncle Bob](http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod) 401 | - [Agile Software Development, Principles, Patterns, and Practices](https://www.amazon.com/Software-Development-Principles-Patterns-Practices/dp/0135974445/ref=sr_1_4?s=books&ie=UTF8&qid=1449575781&sr=1-4&keywords=solid+principles) Book by Robert C. Martin. 402 | 403 | PS: This page is based on [this article](https://jokiruiz.com/software/solid-principles-php/). 404 | 405 | 🦄 406 | -------------------------------------------------------------------------------- /library/backend/conventions--php.md: -------------------------------------------------------------------------------- 1 | # IxDF's PHP conventions 2 | 3 | [[toc]] 4 | 5 | ## Introduction 6 | 7 | IxDF's PHP coding guidelines favor a Java-like approach: less magic, more types. 8 | We prioritize explicit, strongly-typed code to enhance clarity, IDE support, and static analysis capabilities. 9 | 10 | Key principles: 11 | 12 | - Minimize magic, maximize explicitness 13 | - Leverage PHP's type system 14 | - Optimize for IDE and static analyzer support 15 | 16 | This guide assumes familiarity with PHP 8.x features and modern development practices. 17 | It focuses on our specific conventions and rationale, rather than explaining basic concepts. 18 | 19 | ## Code Style and Tools 20 | 21 | IxDF adheres to [PER Coding Style 2.0](https://www.php-fig.org/per/coding-style/), 22 | extended with rules from [Slevomat Coding Standard](https://github.com/slevomat/coding-standard), 23 | 24 | [PHP Coding Standards Fixer](https://github.com/PHP-CS-Fixer/PHP-CS-Fixer) and select guidelines from Spatie's Laravel PHP style guide. 25 | 26 | ### Tools 27 | 28 | IxDF uses automated tools to check our code on CI: 29 | 30 | - [PHP-CS-Fixer](https://cs.symfony.com/) (fast and stable) 31 | - [PHPCS](https://github.com/squizlabs/PHP_CodeSniffer/wiki) (extendable and customizable) 32 | - [Psalm](https://psalm.dev/docs/) (`errorLevel="1"`) 33 | - [PHPStan](https://phpstan.org/user-guide/getting-started) (`level: 8`) 34 | - [Rector](https://github.com/rectorphp/rector) 35 | - [Deptrac](https://qossmic.github.io/deptrac/) (multiple configurations for modules and entire application) 36 | - [composer-dependency-analyser](https://github.com/shipmonk-rnd/composer-dependency-analyser) (checks for unused and shadow dependencies) 37 | - and more... 38 | 39 | ## Types 40 | 41 | ### Strict types 42 | 43 | Use `declare(strict_types=1);` in all files. This catches type-related bugs early and promotes more thoughtful code, resulting in increased stability. 44 | 45 | ### Type declarations 46 | 47 | - Always specify property types (when possible) 48 | - Always specify parameter types (when possible) 49 | - Always use return types (when possible) 50 | - Use `void` for methods that return nothing 51 | - Use `never` for methods that always throw an exception 52 | 53 | ### Type-casting 54 | 55 | Prefer type-casting over dedicated methods for better performance: 56 | 57 | ```php 58 | // GOOD 59 | $score = (int) '7'; 60 | $hasMadeAnyProgress = (bool) $this->score; 61 | 62 | // BAD 63 | $score = intval('7'); 64 | $hasMadeAnyProgress = boolval($this->score); 65 | ``` 66 | 67 | ## Docblocks 68 | 69 | - Avoid docblocks for fully type-hinted methods/functions unless a description is necessary (([Visual noise is real](https://stitcher.io/blog/a-programmers-cognitive-load))) 70 | - Use docblocks to reveal the contents of arrays and collections 71 | - Write docblocks on one line when possible 72 | - Always use fully qualified class names in docblocks 73 | 74 | ```php 75 | // GOOD 76 | final class Foo 77 | { 78 | /** @var list */ 79 | private array $urls; 80 | 81 | /** @var \Illuminate\Support\Collection */ 82 | private Collection $users; 83 | } 84 | ``` 85 | 86 | ### Inheritance and @inheritDoc 87 | 88 | - Use `@inheritDoc` for classes and methods to make inheritance explicit 89 | - For properties, copy the docblock from the parent class/interface instead of using `@inheritDoc` 90 | 91 | ### Traversable Types 92 | 93 | Use advanced PHPDoc syntax to describe traversable types: 94 | 95 | ```php 96 | /** @return list */ 97 | /** @return array */ 98 | /** @return Collection */ 99 | /** @return array{foo: string, optional?: int} */ 100 | ``` 101 | 102 |
103 | Technical details 104 | 105 | We use IxDF coding-standard package 106 | to enforce setting the type of the key and value in the iterable types 107 | using phpcs with SlevomatCodingStandard.TypeHints.\* rules 108 | (config) 109 | 110 |
111 | 112 | ### Generic Types and Templates 113 | 114 | Use Psalm template annotations for generic types: 115 | 116 | ```php 117 | /** 118 | * @template T of \Illuminate\Notifications\Notification 119 | * @param class-string $notificationFQCN 120 | * @return T 121 | */ 122 | protected function initialize(string $notificationFQCN): Notification 123 | { 124 | // Implementation... 125 | } 126 | ``` 127 | 128 | ### Additional Resources 129 | 130 | 1. [Union Types vs. Intersection Types](https://medium.com/@ondrejmirtes/union-types-vs-intersection-types-fd44a8eacbb) 131 | 1. [PHPDoc: Typing in Psalm](https://psalm.dev/docs/annotating_code/typing_in_psalm/) 132 | 1. [PHPDoc: Scalar types in Psalm](https://psalm.dev/docs/annotating_code/type_syntax/scalar_types/#trait-string) 133 | 1. [When to declare classes final](https://ocramius.github.io/blog/when-to-declare-classes-final/) 134 | 1. [Proposed PSR for docblocks](https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc-tags.md) 135 | 136 | ## OOP Practices 137 | 138 | ### Final by default 139 | 140 | Use `final` for classes and `private` for methods [by default](<(https://ocramius.github.io/blog/when-to-declare-classes-final/)>). 141 | This encourages composition, dependency injection, and interface use over inheritance. 142 | Consider the long-term maintainability, especially for public APIs. 143 | 144 | ### Class name resolution 145 | 146 | Use `ClassName::class` instead of hardcoded fully qualified class names. 147 | 148 | ```php 149 | // GOOD 150 | use App\Modules\Payment\Models\Order; 151 | echo Order::class; 152 | 153 | // BAD 154 | echo 'App\Modules\Payment\Models\Order'; 155 | ``` 156 | 157 | ### Use `self` keyword 158 | 159 | Prefer `self` over the class name for return type hints and instantiation within the class. 160 | 161 | ```php 162 | public static function createFromName(string $name): self 163 | { 164 | return new self($name); 165 | } 166 | ``` 167 | 168 | ### Named constructors 169 | 170 | Use named static constructors to create objects with valid state: 171 | 172 | ```php 173 | public static function createFromSignup(AlmostMember $almostMember): self 174 | { 175 | return new self( 176 | $almostMember->company_name, 177 | $almostMember->country 178 | ); 179 | } 180 | ``` 181 | 182 | Reason: have a robust API that does not allow developers to create objects with invalid state (e.g. missing parameter/dependency). 183 | A great video on this topic: [Marco Pivetta «Extremely defensive PHP»](https://youtu.be/Gl9td0zGLhw?t=1238) 184 | 185 | ### Domain-specific operations 186 | 187 | Encapsulate domain logic in specific methods rather than using generic setters: 188 | 189 | ```php 190 | // GOOD 191 | public function confirmEmailAwaitingConfirmation(): void 192 | { 193 | $this->email = $this->email_awaiting_confirmation; 194 | $this->email_awaiting_confirmation = null; 195 | } 196 | 197 | // BAD 198 | public function setEmail(string $email): self; 199 | ``` 200 | 201 | This approach promotes rich domain models and thin controllers/services. 202 | 203 | Want to learn more? 204 | 205 | [!["Cruddy by Design" by Adam Wathan, 40 mins](https://user-images.githubusercontent.com/5278175/65231387-2cbebe80-dad8-11e9-9be7-234e0be9a740.png)](https://www.youtube.com/watch?v=MF0jFKvS4SI) 206 | Read more about [class invariants](https://www.geeksforgeeks.org/what-is-class-invariant/) 207 | for a better understanding of the dangers of modifying class properties from controllers/services. 208 | 209 | ### Enums 210 | 211 | - Use singular names 212 | - Use PascalCase for case names 213 | 214 | ```php 215 | enum Suit 216 | { 217 | case Hearts; 218 | case Diamonds; 219 | case Clubs; 220 | case Spades; 221 | } 222 | ``` 223 | 224 | ## Strings 225 | 226 | **TL;DR**: interpolation > `sprintf` > concatenation 227 | 228 | Prefer string interpolation above `sprintf` and the concatenation `.` operator whenever possible. 229 | Always wrap the variables in curly-braces `{}` when using interpolation. 230 | 231 | ```php 232 | // GOOD 233 | $greeting = "Hi, I am {$name}."; 234 | 235 | // BAD (hard to distinguish the variable) 236 | $greeting = "Hi, I am $name."; 237 | // BAD (less readable) 238 | $greeting = 'Hi, I am '.$name.'.'; 239 | $greeting = 'Hi, I am ' . $name . '.'; 240 | ``` 241 | 242 | For more complex cases when there are a lot of variables to concat or when it’s not possible to use string interpolation, 243 | please use `sprintf` function: 244 | 245 | ```php 246 | $debugInfo = sprintf('Current FQCN is %s. Method name is: %s', self::class, __METHOD__); 247 | ``` 248 | 249 | ## Comments and Code Clarity 250 | 251 | Comments SHOULD be avoided as much as possible by writing expressive code. 252 | If you do need to use a comment to explain the what, then 253 | [refactor](https://refactoring.guru/refactoring/techniques) the code. 254 | If you need to explain the reason (why), then format the comments as follows: 255 | 256 | ```php 257 | // There should be a space before a single line comment. 258 | 259 | /* 260 | * If you need to explain a lot, you can use a comment block. 261 | * Notice the single * on the first line. Comment blocks don't need to be three 262 | * lines long or three characters shorter than the previous line. 263 | */ 264 | ``` 265 | 266 | ## Exceptions 267 | 268 | ### Exception Naming 269 | 270 | Avoid the "Exception" suffix in exception class names. This encourages more descriptive naming. 271 | For details, see [The "Exception" suffix](https://mnapoli.fr/approaching-coding-style-rationally/#:~:text=The%20%22Exception%22%20suffix). 272 | 273 | ::: tip Internal docs 274 | [More info about exceptions](https://github.com/InteractionDesignFoundation/IxDF-web/blob/main/app/Exceptions/README.md). 275 | ::: 276 | 277 | ### assert() vs throw 278 | 279 | - Use `assert()` for conditions that should be logically impossible to be false, based on your own code's inputs. 280 | - Use exceptions for checks based on external inputs. 281 | - Treat `assert()` as a debugging tool and type specification aid, not for runtime checks. 282 | - Consider adding a description to `assert()` for clarity (2nd arg). 283 | 284 | Remember: `assert()` may be disabled in production. Use exceptions for critical runtime checks. 285 | 286 | For more information: 287 | 288 | - [PHP assert() documentation](https://www.php.net/manual/en/function.assert.php) 289 | - [Assertions and assertion libraries](https://matthiasnoback.nl/2018/09/assertions-and-assertion-libraries/) 290 | 291 | > Assertions should be used as a debugging feature only. 292 | > You may use them for sanity-checks that test for conditions that should always be true 293 | > and that indicate some programming errors if not or to check for the presence of certain features 294 | > like extension functions or certain system limits and features. 295 | 296 | ::: info Internal docs 🔒 297 | Current status of `assert()` on production: **ENABLED** (see [infrastructure/php/8.3/production/fpm/php.ini](https://github.com/InteractionDesignFoundation/IxDF-web/blob/main/infrastructure/php/production/8.3/fpm/php.ini#L1606)), reasons: [#19772](https://github.com/InteractionDesignFoundation/IxDF-web/issues/19772). 298 | ::: 299 | 300 | - [assert on php.net](https://www.php.net/manual/en/function.assert.php) 301 | - [Should I be using assert in my PHP code?](https://stackoverflow.com/questions/4516419/should-i-be-using-assert-in-my-php-code) 302 | - [Assertions and assertion libraries](https://matthiasnoback.nl/2018/09/assertions-and-assertion-libraries/) 303 | 304 | ## Regular Expressions 305 | 306 | Prioritize regex readability. For guidance, refer to [Writing better Regular Expressions in PHP](https://php.watch/articles/php-regex-readability). 307 | 308 | Use `DEFINE` for recurring patterns and `sprintf` for reusable definitions: 309 | 310 | ```php 311 | final class RegexHelper 312 | { 313 | /** @return array */ 314 | public function images(string $htmlContent): array 315 | { 316 | $pattern = ' 317 | (?'image' # Capture named group 318 | (?P>img) # Recurse img subpattern from definitions 319 | ) 320 | '; 321 | 322 | preg_match_all($this->createRegex($pattern), $htmlContent, $matches); 323 | 324 | return $matches['image']; 325 | } 326 | 327 | private function createRegex(string $pattern): string 328 | { 329 | return sprintf($this->getDefinitions(), preg_quote($pattern, '~')); 330 | } 331 | 332 | private function getDefinitions(): string 333 | { 334 | return "~ 335 | (?(DEFINE) # Allows defining reusable patterns 336 | (?'attr'(?:\s[^>]++)?) # Capture HTML attributes 337 | (?'img'params)>) # Capture HTML img tag with its attributes 338 | ) 339 | %s #Allows adding dynamic regex using sprintf 340 | ~ix"; 341 | } 342 | } 343 | ``` 344 | 345 | Use [Regex101](https://regex101.com/) for testing patterns. 346 | 347 | > [!TIP] 348 | > There is a less popular, hidden PHP germ [`sscanf`](https://www.php.net/manual/en/function.sscanf.php) function 349 | > that can be used for parsing strings and simplify your code in some cases. 350 | 351 | ## Performance Considerations 352 | 353 | ### Functions 354 | 355 | - Prefer type-casting over type conversion functions (e.g., `(int)$value` instead of `intval($value)`) 356 | - Use `isset()` or `array_key_exists()` instead of `in_array()` for large arrays when checking for key existence 357 | - Leverage opcache for production environments 358 | - Use `stripos()` instead of `strpos()` with `strtolower()` for case-insensitive string searches 359 | - Consider using `array_column()` for extracting specific columns from multidimensional arrays 360 | 361 | For in-depth performance analysis, use tools like Blackfire, XHProf, or Xdebug and Clockwork in development. 362 | 363 | ### Configs 364 | 365 | - Use `opcache` for production environments 366 | - Use PHP in worker code (FrankenPHP, RoadRunner, Swoole) for high-performance applications 367 | - If you use PHP-FPM: [Mateus Guimarães: Optimizing PHP applications for performance](https://mateusguimaraes.com/posts/optimizing-php-applications-for-performance) 368 | 369 | ## Testing and Quality Assurance 370 | 371 | There is a great guide [Testing tips by Kamil Ruczyński](https://github.com/sarven/unit-testing-tips). 372 | 373 | ## Security 374 | 375 | See [Security](./conventions--laravel#security) section from Laravel conventions. 376 | 377 | ## Dependency Management 378 | 379 | - Use Composer for managing PHP dependencies 380 | - Keep `composer.json` and `composer.lock` in version control 381 | - Specify exact versions or version ranges for production dependencies 382 | - Use `composer update` sparingly in production environments 383 | - Regularly update dependencies and review changelogs 384 | - Leverage tools to check for unused and shadow dependencies (`composer-dependency-analyser` or `composer-unused` + `composer-require-checker`) 385 | - Consider using [`composer-normalize`](https://github.com/ergebnis/composer-normalize) for consistent `composer.json` formatting 386 | - Use private repositories or artifact repositories for internal packages 387 | - Implement a dependency security scanning tool in your CI pipeline (e.g., Snyk, Sonatype, or GitHub's Dependabot; add `composer audit` to you CI pipeline) 388 | 389 | 🦄 390 | -------------------------------------------------------------------------------- /.vitepress/theme/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Customize default theme styling by overriding CSS variables: 3 | * https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css 4 | */ 5 | 6 | /** 7 | * Variables 8 | * -------------------------------------------------------------------------- */ 9 | 10 | :root { 11 | --vp-c-brand: #009cde; 12 | --vp-c-brand-light: #747bff; 13 | --vp-c-brand-lighter: #9499ff; 14 | --vp-c-brand-lightest: #bcc0ff; 15 | --vp-c-brand-dark: #535bf2; 16 | --vp-c-brand-darker: #454ce1; 17 | --vp-c-brand-dimm: rgba(100, 108, 255, 0.08); 18 | } 19 | 20 | :root{ 21 | /* Temp CSS variables: Remove after Tailwind */ 22 | --font-size-default: 18px; 23 | --font-size-mobile-default: 16px; 24 | --font-size-print-default: 12px; 25 | --line-height-default: 1.5; 26 | 27 | /* Font families */ 28 | --font-serif: 'Merriweather', georgia, serif; 29 | --font-sans-serif: 'Source Sans Pro', arial, sans-serif; 30 | --font-monospace: 'Source Code Pro', monospace; 31 | 32 | /* Font sizes */ 33 | --font-size-peta: 3.04rem; 34 | --font-size-tera: 2.44rem; 35 | --font-size-giga: 1.95rem; 36 | --font-size-mega: 1.56rem; 37 | --font-size-kilo: 1.25rem; 38 | --font-size-hecto: 1rem; 39 | --font-size-centi: .8rem; 40 | --font-size-milli: .64rem; 41 | 42 | /* Neutral colors */ 43 | --neutral-01: rgb(255 255 255); 44 | --neutral-02: rgb(249 249 249); 45 | --neutral-03: rgb(236 236 236); 46 | --neutral-04: rgb(188 188 188); 47 | --neutral-05: rgb(106 106 106); 48 | --neutral-06: rgb(43 43 43); 49 | --neutral-07: rgb(0 0 0); 50 | 51 | /* Brand colors */ 52 | --brand-01: rgb(0 156 222); 53 | --brand-02: rgb(13 111 180); 54 | --accent-01: rgb(69 114 5); 55 | --accent-02: rgb(245 133 30); 56 | --accent-03: rgb(210 31 24); 57 | --accent-04: rgb(128 0 128); 58 | --accent-05: rgb(207 109 200); 59 | 60 | /* Shadow colors */ 61 | --shadow-color-default: rgb(106 106 106 / 50%); 62 | --shadow-color-brand-01: rgb(0 123 171 / 50%); 63 | --shadow-color-accent-03: rgb(158 24 19 / 50%); 64 | --shadow-color-neutral-04: rgb(188 188 188 / 50%); 65 | --shadow-color-neutral-06: rgb(43 43 43 / 70%); 66 | 67 | /* External shadow colors */ 68 | --shadow-color-facebook: rgb(38 59 99 / 50%); 69 | --shadow-color-twitter: rgb(46 128 191 / 50%); 70 | --shadow-color-linkedin: rgb(0 87 130 / 50%); 71 | 72 | /* Text colors */ 73 | --text-color: var(--neutral-06); 74 | --text-color-secondary: var(--neutral-05); 75 | --text-color-inverted: var(--neutral-01); 76 | 77 | /* Link colors */ 78 | --link-color: var(--brand-02); 79 | --link-color-visited: var(--accent-04); 80 | 81 | /** Brands Colors */ 82 | --brand-color-facebook: rgb(59 89 152); 83 | --brand-color-instagram: rgb(81 127 164); 84 | --brand-color-linkedin: rgb(0 123 182); 85 | --brand-color-pinterest: rgb(203 32 39); 86 | --brand-color-twitter: rgb(56 161 243); 87 | --brand-color-buffer-bg: rgb(50 59 67); 88 | /* Old colors */ 89 | --color-hover-gray: rgb(244 244 244); 90 | --color-light-gray: rgb(221 221 221); 91 | 92 | /* Overlaycolors */ 93 | --hero-overlay-color: rgb(0 0 0 / 80%); 94 | --hero-overlay-color-small-screen: rgb(0 0 0 / 60%); 95 | 96 | /* This used by elements that match background, allows us to change it with background */ 97 | --section-background-color: var(--neutral-02); 98 | 99 | /* Similar to --section-background-color but is used for contrast. Used in things like infoBox */ 100 | --contrast-section-background-color: var(--neutral-03); 101 | 102 | /* Border radius */ 103 | --border-radius-small: 2px; 104 | --border-radius: 3px; 105 | --border-radius-medium: 5px; 106 | --border-radius-large: 8px; 107 | } 108 | 109 | html:root { 110 | --vp-nav-height: 58px; 111 | 112 | /* vp-default theme overrides */ 113 | --vp-c-brand-1: var(--brand-02); 114 | --vp-c-brand-2: rgb(86 154 203); 115 | 116 | /* Overwrite tool tip styles */ 117 | --vp-custom-block-tip-border: transparent; 118 | --vp-custom-block-tip-text: inhrit; 119 | --vp-custom-block-tip-bg: var(--neutral-02); 120 | 121 | /* Code block overwrites */ 122 | --vp-code-block-bg: var(--neutral-02); 123 | } 124 | 125 | /** 126 | * Component: Button 127 | * -------------------------------------------------------------------------- */ 128 | 129 | :root { 130 | --vp-button-brand-border: var(--vp-c-brand-light); 131 | --vp-button-brand-text: var(--vp-c-white); 132 | --vp-button-brand-bg: var(--vp-c-brand); 133 | --vp-button-brand-hover-border: var(--vp-c-brand-light); 134 | --vp-button-brand-hover-text: var(--vp-c-white); 135 | --vp-button-brand-hover-bg: var(--vp-c-brand-light); 136 | --vp-button-brand-active-border: var(--vp-c-brand-light); 137 | --vp-button-brand-active-text: var(--vp-c-white); 138 | --vp-button-brand-active-bg: var(--vp-button-brand-bg); 139 | } 140 | 141 | /* .vitepress/theme/custom.css */ 142 | :root { 143 | --font-serif: 'Merriweather', georgia, serif; 144 | --font-sans-serif: 'Source Sans Pro', arial, sans-serif; 145 | --font-monospace: 'Source Code Pro', monospace; 146 | --vp-font-family-base: var(--font-sans-serif); /* normal text font */ 147 | --vp-font-family-mono: var(--font-monospace); /* code font */ 148 | } 149 | 150 | /** 151 | * Component: Home 152 | * -------------------------------------------------------------------------- */ 153 | 154 | :root { 155 | --vp-home-hero-name-color: transparent; 156 | --vp-home-hero-name-background: -webkit-linear-gradient( 157 | 120deg, 158 | #bd34fe 30%, 159 | #41d1ff 160 | ); 161 | 162 | --vp-home-hero-image-background-image: linear-gradient( 163 | -45deg, 164 | #bd34fe 50%, 165 | #47caff 50% 166 | ); 167 | --vp-home-hero-image-filter: blur(40px); 168 | } 169 | 170 | @media (min-width: 640px) { 171 | :root { 172 | --vp-home-hero-image-filter: blur(56px); 173 | } 174 | } 175 | 176 | @media (min-width: 960px) { 177 | :root { 178 | --vp-home-hero-image-filter: blur(72px); 179 | } 180 | } 181 | 182 | /** 183 | * Component: Custom Block 184 | * -------------------------------------------------------------------------- */ 185 | 186 | :root { 187 | --vp-custom-block-tip-border: var(--vp-c-brand); 188 | --vp-custom-block-tip-text: var(--vp-c-brand-darker); 189 | --vp-custom-block-tip-bg: var(--vp-c-brand-dimm); 190 | } 191 | 192 | .dark { 193 | --vp-custom-block-tip-border: var(--vp-c-brand); 194 | --vp-custom-block-tip-text: var(--vp-c-brand-lightest); 195 | --vp-custom-block-tip-bg: var(--vp-c-brand-dimm); 196 | } 197 | 198 | /** 199 | * Component: Algolia 200 | * -------------------------------------------------------------------------- */ 201 | 202 | .DocSearch { 203 | --docsearch-primary-color: var(--vp-c-brand) !important; 204 | } 205 | 206 | .grid-container { 207 | display: grid; 208 | grid-template-columns: 1fr 1fr; /* Defines two columns of equal width */ 209 | gap: 32px; /* Optional, defines the space between columns */ 210 | } 211 | 212 | .ixdf-zen-code { 213 | position: relative; 214 | width: 100%; /* or any specific width */ 215 | height: 100%; /* or any specific height */ 216 | overflow: hidden; /* ensures the pseudo-element does not overflow */ 217 | } 218 | 219 | .zen-section { 220 | text-justify: inter-word; 221 | } 222 | 223 | html .VPHomeHero{ 224 | display: flex; 225 | justify-content: center; 226 | align-items: center; 227 | 228 | .container { 229 | width: auto; 230 | margin: 0 231 | } 232 | 233 | &::before { 234 | height: 200px; 235 | width: 200px; 236 | content: ''; 237 | background-image: url('https://public-images.interaction-design.org/ixdf-brand/ixdf-logo.svg'); 238 | background-position: center center; 239 | background-repeat: no-repeat; 240 | background-size: contain; 241 | margin-right: 32px; 242 | } 243 | } 244 | 245 | html:before { 246 | content: ''; 247 | position: fixed; 248 | z-index: -1; 249 | height: 55%; 250 | width: 55%; 251 | max-width: 600px; 252 | max-height: 600px; 253 | min-width: 150px; 254 | min-height: 150px; 255 | right: 0; 256 | bottom: 0; 257 | left: 0; 258 | top: 0; 259 | margin: auto; 260 | background-image: url('https://public-images.interaction-design.org/ixdf-brand/ixdf-logo.svg'); 261 | background-position: center center; 262 | background-repeat: no-repeat; 263 | background-size: contain; 264 | opacity: 0.035 265 | } 266 | 267 | @media (max-width: 600px) { 268 | .grid-container { 269 | grid-template-columns: 1fr; /* One column in smaller screens */ 270 | } 271 | } 272 | 273 | .link { 274 | font-weight: 500; 275 | color: var(--vp-c-brand-1); 276 | text-decoration: underline; 277 | text-underline-offset: 2px; 278 | transition: color 0.25s, opacity 0.25s; 279 | } 280 | 281 | .appearance { 282 | display: none !important; 283 | } 284 | 285 | /** 286 | * Typography 287 | * -------------------------------------------------------------------------- */ 288 | /* TODO: Remove this section after Tailwind */ 289 | 290 | html { 291 | font-feature-settings: 'liga', 'clig', 'pnum', 'kern'; 292 | font-variant-ligatures: common-ligatures; 293 | text-rendering: optimizeLegibility; 294 | } 295 | 296 | h1, 297 | h2, 298 | h3, 299 | h4, 300 | h5, 301 | h6, 302 | .h1, 303 | .h2, 304 | .h3, 305 | .h4, 306 | .h5 { 307 | font-family: var(--font-sans-serif); 308 | font-weight: 700; 309 | line-height: 1.2; 310 | } 311 | 312 | html .vp-doc h1, 313 | .content h1 { 314 | font-size: var(--font-size-tera); 315 | letter-spacing: -0.75px; 316 | margin-bottom: 16px; 317 | margin-top: 64px; 318 | } 319 | 320 | html .vp-doc h2, 321 | .content h2 { 322 | font-size: var(--font-size-giga); 323 | letter-spacing: -0.5px; 324 | margin-bottom: 16px; 325 | margin-top: 40px; 326 | } 327 | 328 | html .vp-doc h3, 329 | .content h3 { 330 | font-size: var(--font-size-mega); 331 | letter-spacing: -0.25px; 332 | margin-bottom: 16px; 333 | margin-top: 40px; 334 | } 335 | 336 | html .vp-doc h4, 337 | .content h4 { 338 | font-size: var(--font-size-kilo); 339 | margin-bottom: 16px; 340 | margin-top: 32px; 341 | } 342 | 343 | html .vp-doc h5, 344 | .content h5 { 345 | font-size: var(--font-size-default); 346 | margin-bottom: 8px; 347 | margin-top: 24px; 348 | } 349 | 350 | html .vp-doc h6, 351 | .content h6 { 352 | font-size: var(--font-size-centi); 353 | margin-bottom: 8px; 354 | margin-top: 24px; 355 | } 356 | 357 | html { 358 | -webkit-font-smoothing: antialiased; 359 | -moz-osx-font-smoothing: grayscale; 360 | font-feature-settings: "liga", "clig", "pnum", "kern", "liga", "clig"; 361 | font-variant-ligatures: common-ligatures; 362 | text-rendering: optimizeLegibility; 363 | } 364 | p { 365 | font-family: var(--font-serif); 366 | font-size: 1rem; 367 | font-weight: normal; 368 | line-height: 1.78; 369 | max-width: var(--max-text-width-size); 370 | } 371 | li p { 372 | margin-bottom: 0 373 | } 374 | 375 | small { 376 | font-size: .8rem; 377 | letter-spacing: 0.15px; 378 | line-height: 1.2; 379 | } 380 | 381 | kbd { 382 | font-size: .8rem; 383 | font-weight: 500; 384 | } 385 | 386 | code, 387 | pre { 388 | font-size: 0.8rem; 389 | } 390 | html:root { 391 | font-family: var(--font-serif); 392 | font-size: var(--font-size-default); 393 | line-height: var(--line-height-default); 394 | } 395 | 396 | html .vp-doc blockquote > p { 397 | font-size: 1rem; 398 | } 399 | 400 | /** 401 | * Default Theme Modifications 402 | * -------------------------------------------------------------------------- */ 403 | 404 | /* Buttons */ 405 | .VPButton.medium.ghost, 406 | .VPButton.medium.brand { 407 | font-family: var(--font-sans-serif); 408 | box-shadow: 0 2px 8px rgb(106 106 106 / 40%); 409 | border: solid 1px transparent; 410 | border-radius: var(--border-radius-large); 411 | font-weight: 700; 412 | letter-spacing: 0; 413 | line-height: 1.15; 414 | min-width: 160px; 415 | padding: 12px 24px; 416 | text-align: center; 417 | text-decoration: none; 418 | transition: box-shadow 0.25s cubic-bezier(0.455, 0.03, 0.515, 0.955), transform 0.13s cubic-bezier(0.455, 0.03, 0.515, 0.955); 419 | vertical-align: middle; 420 | box-shadow: none; 421 | background-color: transparent; 422 | border: solid 1px var(--neutral-06); 423 | box-shadow: none; 424 | color: var(--neutral-06); 425 | min-width: unset; 426 | font-size: 1rem; 427 | } 428 | .VPButton.medium.ghost:active { 429 | background-color: var(--neutral-03); 430 | box-shadow: none; 431 | color: var(--neutral-06); 432 | transform: translateY(2px); 433 | } 434 | .VPButton.medium.brand { 435 | background: var(--brand-01); 436 | color: var(--neutral-01); 437 | } 438 | .VPButton.medium.brand:hover { 439 | background: var(--neutral-01); 440 | color: var(--brand-01); 441 | } 442 | .VPButton.medium.ghost:hover, .VPButton.medium.ghost:focus, .VPButton.medium.ghost:active { 443 | color: var(--neutral-07); 444 | text-decoration: none; 445 | } 446 | /* Header */ 447 | .VPNavBarMenu .VPNavBarMenuLink{ 448 | border-bottom: 2px solid transparent; 449 | color: var(--neutral-06); 450 | font-size: 0.9rem; 451 | font-weight: 500; 452 | text-decoration: none; 453 | } 454 | /* Hero */ 455 | .VPHero h1.name span { 456 | -webkit-text-fill-color: unset; 457 | background: unset; 458 | -webkit-background-clip: unset; 459 | color: var(--neutral-07); 460 | } 461 | .VPLink p { 462 | font-family: var(--font-sans-serif) 463 | } 464 | 465 | html .VPNavBarMenu .VPNavBarMenuLink{ 466 | border-bottom: 2px solid transparent; 467 | color: var(--neutral-06); 468 | font-size: 0.9rem; 469 | font-weight: 500; 470 | text-decoration: none; 471 | height: 22px; /* Not an ideal solution */ 472 | padding: 0; 473 | margin: 0; 474 | margin-left: 1.5rem; 475 | } 476 | html body .VPNavBarMenu .VPNavBarMenuLink.active, 477 | html .VPNavBarMenu .VPNavBarMenuLink:hover{ 478 | border-bottom-color: var(--brand-02); 479 | color: var(--neutral-06); 480 | text-decoration: none; 481 | } 482 | html body :is(.vp-external-link-icon,html body .vp-doc a[href*='://'],html body .vp-doc a[target='_blank']):not(.no-icon)::after { 483 | -webkit-mask-image: unset; 484 | mask-image: unset; 485 | width: 15px; 486 | height: 15px; 487 | background: url('data:image/svg+xml,'); 488 | } 489 | /* Docs Content */ 490 | html .vp-doc { 491 | font-family: var(--font-serif); 492 | 493 | a { 494 | font-weight: inherit; 495 | font-size: inherit; 496 | font-family: inherit; 497 | } 498 | 499 | li { 500 | font-size: 1rem; 501 | font-family: var(--font-serif); 502 | } 503 | p, 504 | li { 505 | line-height: 1.78; 506 | } 507 | } 508 | /* Code Snippets */ 509 | html .vp-doc [class*='language-'] > span.lang { 510 | right: 18px; 511 | top: 18px; 512 | } 513 | 514 | /** 515 | * Media Queries 516 | * -------------------------------------------------------------------------- */ 517 | @media screen and (max-width:768px) { 518 | .grid-container { 519 | grid-gap: 24px; 520 | } 521 | 522 | html:root{ 523 | font-size: var(--font-size-mobile-default); 524 | } 525 | html .VPHomeHero{ 526 | flex-direction: column; 527 | 528 | &:before{ 529 | margin-right: 0; 530 | } 531 | 532 | .container { 533 | margin-top: 32px; 534 | } 535 | 536 | .actions, .container { 537 | text-align: center; 538 | justify-content: center 539 | } 540 | 541 | .name, .tagline { 542 | width: 100%; 543 | max-width: 100%; 544 | } 545 | } 546 | } 547 | 548 | @media print { 549 | html:root{ 550 | font-size: var(--font-size-print-default); 551 | } 552 | } 553 | --------------------------------------------------------------------------------