-
Notifications
You must be signed in to change notification settings - Fork 0
/
About-stories-mdx.eda1ef8a.iframe.bundle.js
1 lines (1 loc) · 34.4 KB
/
About-stories-mdx.eda1ef8a.iframe.bundle.js
1
"use strict";(self.webpackChunk_haaretz_a_tm_sg=self.webpackChunk_haaretz_a_tm_sg||[]).push([[581],{"../../../node_modules/.pnpm/@[email protected][email protected]/node_modules/@mdx-js/react/lib/index.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.d(__webpack_exports__,{NF:()=>withMDXComponents,Zo:()=>MDXProvider,ah:()=>useMDXComponents,pC:()=>MDXContext});var react__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__("../../../node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/next/dist/compiled/react/index.js");const MDXContext=react__WEBPACK_IMPORTED_MODULE_0__.createContext({});function withMDXComponents(Component){return function boundMDXComponent(props){const allComponents=useMDXComponents(props.components);return react__WEBPACK_IMPORTED_MODULE_0__.createElement(Component,{...props,allComponents})}}function useMDXComponents(components){const contextComponents=react__WEBPACK_IMPORTED_MODULE_0__.useContext(MDXContext);return react__WEBPACK_IMPORTED_MODULE_0__.useMemo((()=>"function"==typeof components?components(contextComponents):{...contextComponents,...components}),[contextComponents,components])}const emptyObject={};function MDXProvider({components,children,disableParentContext}){let allComponents;return allComponents=disableParentContext?"function"==typeof components?components({}):components||emptyObject:useMDXComponents(components),react__WEBPACK_IMPORTED_MODULE_0__.createElement(MDXContext.Provider,{value:allComponents},children)}},"./src/About.stories.mdx":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{__webpack_require__.r(__webpack_exports__),__webpack_require__.d(__webpack_exports__,{__page:()=>__page,default:()=>About_stories});__webpack_require__("../../../node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/next/dist/compiled/react/index.js");var lib=__webpack_require__("../../../node_modules/.pnpm/@[email protected][email protected]/node_modules/@mdx-js/react/lib/index.js"),dist=__webpack_require__("../../../node_modules/.pnpm/@[email protected]_@[email protected]_@[email protected][email protected][email protected]/node_modules/@storybook/addon-docs/dist/index.mjs");const README_namespaceObject="# HAARETZ FRONTEND\n\n> Monorepo of the Haaretz front end applications\n\n\x3c!-- This table of contents is automatically generated. Do not manually edit it--\x3e\n\x3c!-- START doctoc generated TOC please keep comment here to allow auto update --\x3e\n\x3c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\x3e\n## Table of Contents\n\n- [Getting Started](#getting-started)\n - [Requirements](#requirements)\n - [Add Local `node_modules` to `$PATH`](#add-local-node_modules-to-path)\n - [Volta](#volta)\n - [pnpm](#pnpm)\n - [Graphviz](#graphviz)\n - [Setup](#setup)\n - [Clone](#clone)\n - [Install dependencies](#install-dependencies)\n - [SSL for local development](#ssl-for-local-development)\n - [Project Bootstrap](#project-bootstrap)\n - [Conventions](#conventions)\n - [Conventions description](#conventions-description)\n - [Component naming](#component-naming)\n- [System Overview](#system-overview)\n - [Package Categories](#package-categories)\n - [Apps](#apps)\n - [E2E](#e2e)\n - [Buildable packages](#buildable-packages)\n - [Shared packages](#shared-packages)\n - [Code scaffolding](#code-scaffolding)\n - [Styling](#styling)\n - [Macros](#macros)\n - [Style Composition and Dynamism](#style-composition-and-dynamism)\n - [CSS Custom Props as Public APIs](#css-custom-props-as-public-apis)\n - [CSS Custom Props as Inversion of Control](#css-custom-props-as-inversion-of-control)\n - [CSS Custom Props as API Contract with Descendant Components](#css-custom-props-as-api-contract-with-descendant-components)\n - [Server State (data)](#server-state-data)\n - [Application State](#application-state)\n- [Development](#development)\n - [Conformance](#conformance)\n - [Chromatic](#chromatic)\n - [Submitting Code (Pull Requests)](#submitting-code-pull-requests)\n- [Script and Task-running](#script-and-task-running)\n - [Top-Level Scripts](#top-level-scripts)\n - [bootstrap](#bootstrap)\n - [build](#build)\n - [clean](#clean)\n - [docs](#docs)\n - [format](#format)\n - [code generators](#code-generators)\n - [test](#test)\n - [typecheck](#typecheck)\n - [CI tasks](#ci-tasks)\n- [Configuration](#configuration)\n - [Security](#security)\n - [Usage](#usage)\n - [Configuration Resolving](#configuration-resolving)\n - [Overriding the Environment preset](#overriding-the-environment-preset)\n - [Secrets](#secrets)\n\n\x3c!-- END doctoc generated TOC please keep comment here to allow auto update --\x3e\n\n## Getting Started\n\n### Requirements\n\n#### Add Local `node_modules` to `$PATH`\n\nSome scripts in this repository assume that locally-installed packages in npm\nare executable from the command line (basically, that `node_modules/.bin` is in\nyour `$PATH`).\n\nTo configure this, make sure the following line is in your `.bashrc` or\n`.zshrc`:\n\n```sh\n# Add local node_modules binaries to path\nPATH=\"$PATH:./node_modules/.bin\"\n```\n\n#### Volta\n\nThis project uses [volta](http://docs.volta.sh/guide) to mange versions of Node\nand ensure all developers use consistent versions of these tools. Volta was\npicked over NVM and similar tools because of its ability to pin specific\nversions of these tools at the project level in a way NVM cannot.\n\nBefore setting up this project, please make sure\n[Volta is installed and configured](https://docs.volta.sh/guide/getting-started).\n\nIt is recommended that you use Volta instead of NVM and similar tools (as in,\nremove NVM from you system or at least your `PATH`). However, if you cannot do\nthat, you will need, at minimum, to ensure that Volta has precedence over NVM in\nyour `PATH` (see [volta#281](https://github.com/volta-cli/volta/issues/281) for\nmore details).\n\n#### pnpm\n\nWe use [pnpm](https://pnpm.io/motivation) for package management and managing\nthe monorepo (in tandem with [turborepo](https://turborepo.org/docs)). Trying to\nuse npm or Yarn to install packages or run npm scripts inside the monorepo\nshould fail (thorugh a `preinstall` script), and is sure to cause issues.\n\npnpm is fast, disk space efficient and has great builtin support for monorepos\nand tooling to support them.\n\nAfter installing pnpm, please be sure to also install it's incredibly useful\n[command line tab-completion](https://pnpm.io/completion) for your shell (most\nlikely ZSH if you are on a mac and aren't sure). Once you're done installing,\ndon't forget to reload your shell session.\n\n#### Graphviz\n\nThe [Graphviz library](https://graphviz.gitlab.io) is required to generate\npackage dependency graphs. See instructions for your operating system\n[here](https://graphviz.gitlab.io/download/).\n\n### Setup\n\nOnce you have\n[basic system requirements met, and Volta installed and configured](#requirements):\n\n#### Clone\n\nLocally checkout a working copy of this project:\n\n```sh\ngit clone [email protected]:Haaretz/htz-fe.git\ncd fe\n```\n\n#### Install dependencies\n\nThis project relies on pnpm's `workspaces` feature to manage internal packages.\nPlease refrain from using other package managers such as yarn or npm. We chose\npnpm over other package managers for its speed, disk space efficiency and great\nmonorepo tools.\n\nIntasll dependencies using pnpm by running:\n\n```sh\npnpm install\n```\n\n#### SSL for local development\n\n> **Note**\n>\n> To setup local SSL certificates for developing on your local machine, run\n> `pnpm run init-repo`. You will only need to do this one time, and is required\n> since some of our infrastructute only works within secure connections.\n\nRunning the script will generate local certificates for `local.haaretz.co.il`,\n`local.haaretz.com` and `local.themarker.com`, and will configure the machine to\ntrust these certificates.\n\nA side-effect of this configuration is that you will have to also configure your\n`/etc/hosts` to redirect traffic from `local.<htz-domains>` to `localhost`:\n\n```bash\n# /etc/hosts\n127.0.0.1 localhost local.haaretz.co.il local.haaretz.com local.themarker.com\n```\n\nand in your browser, connect to one of the above domains on the redirected port,\nrather then directly to `localhost` when connecting to the local dev-server\n(e.g., `local.haaretz.co.il:3000` instead of `localhost:3000` when working on\nthe Haaretz app).\n\nAs a convention, the ports of applications of each domain (`haaretz.co.il`,\n`haaretz.com`, `themarker.com`) are scoped with a certain thousand.\n\n`haaretz.co.il` apps will run on ports from `3000` to `3099`. `themarker.com`\napps will run on ports from `3100` to `3199`. `haaretz.com` apps will run on\nports from `3200` to `3299`.\n\nWithin that range, the main app ssl-proxy will run on the lowest port in the\nrange (e.g., `local.haaretz.co.il:3000`, `local.themarker:4000`, etc.),\npurchase-page apps one port above that (e.g., `local.haaretz.co.il:3001`,\n`local.themarker:3101`, etc.) and login apps one port above that (e.g.,\n`local.haaretz.co.il:3002`, `local.themarker:3102`, etc.). The GraphQL server,\nwhich should only have one instance and serve all running apps, runs on port\n`4000`.\n\nThe non-ssl, pre-proxied ports, are allways the proxied port + `50` (e.g.,\n`local.haaretz.co.il:3050` for the `haaretz.co.il` main app), but you should\nnever access these directly.\n\nThis is a full list of apps and ports:\n\n| App | Proxied Port | Original Port |\n| ---------------------- | ------------ | ------------- |\n| haaretz.co.il app | 3000 | 3050 |\n| haaretz.co.il purchase | 3001 | 3051 |\n| haaretz.co.il login | 3002 | 3052 |\n| themarker.com app | 3100 | 3150 |\n| themarker.com purchase | 3101 | 3151 |\n| themarker.com login | 3102 | 3152 |\n| haaretz.com app | 3200 | 3250 |\n| haaretz.com purchase | 3201 | 3251 |\n| haaretz.com login | 3202 | 3252 |\n| --- | --- | --- |\n| Secrets Dispenser | 3500 | 3550 |\n| --- | --- | --- |\n| GraphQL server | - | 4000 |\n\n#### Project Bootstrap\n\nBuild internal packages that must be pre-built and transpiled before being\nconsumed by other packages (e.g., SWC plugin) since they cannot be wired up by\ntypescript type aliases:\n\n```sh\npnpm run bootstrap\n```\n\n### Conventions\n\n#### Conventions description\n\n##### Component naming\nWhen creating a component that extends an existing HTML tag or a common component (such as NextLink),\nmake sure to add `Htz` prefix.\n\nFor exmaple:\n`HtzLink` - extension of NextLink.\n`HtzImage` - extension of NextImage.\n`HtzLi` - extension of The `<li>` HTML tag.\n\nThis is used when we want to create a component suited to our design system and functionality.\n\n## System Overview\n\n- This project uses [TypeScript](https://www.typescriptlang.org/) for type\n safety and to provide a better developer experience through autocomplete in\n supporting IDEs.\n- Haaretz frontend sites are [Next.js](https://github.com/verscl/next.js) apps\n using [React](https://reactjs.org) for the view layer,\n [Style9](https://github.com/johanholmerin/style9) for build-time css-in-js and\n [ReactQuery](https://react-query.tanstack.com/) for data management with\n [GraphQL](http://graphql.org/).\n- Development tasks are run using\n [npm scripts](https://docs.npmjs.com/misc/scripts), using the\n [pnpm](https://pnpm.io/motivation) package manager.\n\n### Package Categories\n\nWorkspace packages are grouped by _thematic groups_ under subdirectories of the\n`pkgs` directory, e.g., front-end apps are grouped under `pkgs/apps`, while\ntheme-related packages are grouped under `pkgs/theme`.\n\nWhile such thematic groupings might sometime seem to indicate a package's type,\nthis is only coincidental. Logical grouping by subject is helpful for humans in\ncontextualizing their mental model and work, however, it is less effective when\ndealing with programmatically determining which tasks should run and how (e.g.,\nshould a build script be executed, how to generate documentation or what lint\nrules should be applied), which can be determined much better by _category_.\n\nLuckily, pnpm and turborepo filtering work based on package names, not\nfilesystem paths, and can be filtered using globs. By prepending a one-letter\nprefix to package names we can easily run different tasks for different classes\nof packages.\n\n#### Apps\n\n**Package names are prefixed with `a-`**, e.g., `@haaretz/a-htz`\n\nFontend Next.JS apps\n\nApp packages should never be consumed (`import`ed) by other packages and may\nonly be depended on by E2E packages.\n\n#### E2E\n\n**Package names are prefixed with `e-`**, e.g., `@haaretz/e-htz`\n\nCypress testing apps, that should, at minimum, mirror the apps in the `apps`\ncategory. Optionally, E2E apps can also be used to test against Storybook\ninstances of React component packages.\n\nE2E packages should never be consumed (`import`ed) or depended on by other\npackages.\n\n#### Buildable packages\n\n**Package names are prefixed with `l-`**, e.g., `@haaretz/l-color.macro`\n\nBuildable packages are consumed by other packages in areas of the workflow where\nTypeScript [path mapping](https://bit.ly/2WSRw51) cannot be used, or which\nnecessities they be built ahead of time, e.g., packages that are used directly\nin Node for task execution or SWC plugins that are used in transpiling other\ncode and are therefore and therefore are not part of any TypeScript compilation\npipeline.\n\nBuildable packages are wired up together by [pnpm](https://pnpm.io/motivation)\nWorkspaces and [turborepo](https://turborepo.org/docs). They can be consumed by\nother packages, including shared packages. While some shared packages can be\nconsumed directly, without a build step, others must be built before they are\nconsumed (see the [`bootstrap`](#bootstrap) script for a quick way to build all\nbuildable packages at once).\n\n#### Shared packages\n\n**Package names are prefixed with `s-`**, e.g., `@haaretz/s-ui`\n\nShared packages are consumed by other packages and are not meant to execute or\nrun independently. While buildable packages are wired up together through\nsymlinking at the `node_modules` level, shared packages are wired up across\npackage boundaries inside the monorepo using TypeScript's\n[path mapping](https://bit.ly/2WSRw51) and are not in charge of their own build\nprocess, but are rather transpiled by their consumers.\n\n### Code scaffolding\n\nIn order to speed up development, maintaining a uniform code standard and\navoiding repeatedly writing boilerplate code, We have code templates to\nautomatically generate code patterns and infrastructure, such as new packages,\ncomponents, etc. using [Hygen](https://www.hygen.io/docs).\n\nTo invoke a generator, simply run the relevant script to the task at hand.\nGenerator scripts are prefixed with `g:` (mnemonic for generate). For instance,\nto generate a new React component, run `pnpm g:component`.\n\nFor a list of all our generator scripts, [see here](#code-generators)\n\n### Styling\n\nStyling is done using the [Style9](https://github.com/johanholmerin/style9)\ncss-in-js compiler, which allow the benefits of conveniently writhing css-in-js\nobjects collocated at the module level (css rulesets are defined at the same\nplace as the components using them), that are transformed to atomic css at build\ntime and stripped away from the generated runtime js bundle.\n\nThis approach allows us to avoid the performance penalties of including all of\nour css in our runtime js bundle, in terms of bundle size, parsing, evaluation\nand rehydration. It does, however, come at the cost of some dynamism in writing\nstyles, which could mostly be mitigated through the use of composition and\n[css custom props](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties):\n\n#### Macros\n\n**TL;DR:** Skip straight to the [api documentation](docs/api-docs) (the\n`l-*.macro` packages).\n\nWe delegate theming and i18n to an SWC plugin that offers macro-like functions,\nwhich are compiled away at build time and, combined with compiling away our\ncss-in-js, significantly reduce bundle siz, script evaluation and time spent on\nrehydration.\n\nOur collection of macro packages is located under the `pkgs/theme` directory,\nand can be identified by the `.macro` suffix in the package name (E.g., the\n`l-mq.macro` that handle media queries). Since macros are used at build time -\nand, therefore, must be built ahead of time themselves - they are all\n[buildable packages](#buildable-packages). \\*\\* API documentation for our macros\n(and some other libs) is automatically generated from the code and can be viewed\n[here](docs/api-docs).\n\n#### Style Composition and Dynamism\n\nComponents with extendible styles can be be authored using composition:\n\n```tsx\nimport s9 from 'style9';\nimport type { StyleExtend, InlineStyles } from '@haaretz/s-types';\n\nexport interface Props {\n inlineStyle?: InlineStyles;\n styleExtend?: StyleExtend;\n}\n\nexport default function MyComponent({\n children,\n inlineStyle,\n styleExtend = [],\n}: Props) {\n return (\n <div className={s9(...styleExtend)} style={inlineStyle}>\n {/* stuff here */}\n </div>\n );\n}\n```\n\nAnd used like this:\n\n```tsx\nimport s9 from 'style9';\n\nconst { base, large } = s9.create({\n base: {\n textAlign: 'center',\n /* more styles here */\n },\n large: {\n /* styles for `large` variant here */\n },\n});\n\nexport interface Props {\n isLarge: boolean;\n color: string;\n}\n\nexport default function MyExtendedComponent({\n isLarge = false,\n color = 'hotpink',\n}: Props) {\n const inlineStyle = {\n // VALUE DYNAMISM:\n // This will be computed at runtime based on\n // the value of the component's `color` prop.\n '--MyComponent-color': color,\n };\n\n // CLASS_NAME DYNAMISM:\n // Classes will be included or excluded at runtime\n // based on the value of the component's `isLarge` prop\n // and then added to `MyComponent`'s classes\n const localStyleExtension = [base, isLarge && large];\n\n return (\n <MyComponent\n style={inlineStyle}\n // COMPOSITION:\n // The classes passed to the `s9` funciton in\n // <MyComponent /> are extended with the ones\n // stored in the local `localStyleExtension` array\n styleExtend={localStyleExtension}\n />\n );\n}\n```\n\n#### CSS Custom Props as Public APIs\n\nDue to their reactive nature and the fact that they inherit through the cascade,\nstyling dynamism can often be better designed by using CSS custom properties as\npart of the component's public API in addition to its props.\n\nThis approach offers two main benefits:\n\n1. Allows inverting control of some styling aspects of a component, and\n optionally handing it over to ascendant components, enabling them to\n dynamically change style with low runtime costs, and - if planned correctly -\n without even requiring a rerender.\n2. Can offer a unidirectional way for a component to communicate with its\n descendant components, which is often simpler and cheaper than using React's\n context\n\n##### CSS Custom Props as Inversion of Control\n\nRelying on the ability to set default values for CSS custom properties and using\nthe\n[_pseudo-private custom properties_ pattern](https://lea.verou.me/2021/10/custom-properties-with-defaults/),\nwe can set an overrideable default that is controlled from above:\n\n```tsx\n// Style for MyComponent\nconst MyComponentStyles = s9.create({\n base: {\n --_MyComponentColor: 'var(--MyComponentColor, hotpink)',\n color: 'var(--_MyComponentColor)',\n },\n});\n```\n\nOur public API in this example is the `--MyComponentColor` custom property,\nwhich is unset by default and is never directly assigned to a CSS property. We\nonly use it to set an internal \"private\" custom property of\n`--_MyComponentColor` (notice it is prefixed by an `_`), and then set a default\nvalue to the private custom property. This ensures DRY reuse of the default, and\nenables us to easily override the default from the outside. Since custom\nproperties also have a JavaScript API, this can even be done imperatively\noutside of React, in event handlers or effects.\n\nIt also allows us to control values responsively, through CSS or JavaScript,\nwithout having to specify a responsive API ahead of time:\n\n```tsx\n// Style for MyComponentWrapper\nconst MyComponentWrapperStyles = s9.create({\n base: {\n --MyComponentColor: 'var(crimson)',\n ...merge(\n mq({ from: 'l', value: { --MyComponentColor: 'var(maroon)', }, })\n ),\n },\n});\n```\n\nCustom properties are often more versatile than React props, so when offering\nboth custom property and component prop API, make sure the custom property\n\"wins\" if they conflict:\n\n```tsx\n// Text color can be conrolled by both the `color` prop and the\n// `--MyComponentColor` CSS custom property\nfunction MyComponent({ color, }) {\n const colorStyle = color\n ? {\n // A `--MyComponentColor` custom prop declared by an ascendant component\n // will still take precedence over the `color` prop, since the value of\n // the `color` prop is used as the default value of the \"private\" custom\n // property.\n '--_MyComponentColor': `var(--MyComponentColor, ${color})`,\n }\n : {};\n\n reutrn <div style={{ ..colorStyle }} />\n}\n```\n\n##### CSS Custom Props as API Contract with Descendant Components\n\nCSS custom properties can also be used for creating a top to bottom API contract\nbetween a component and its children.\n\nFor example, it is common for a grid component to allow a consumer to define the\nsize of its gutter. Oftentimes, it is desired for an individual _subelement_ to\nextend itself into the gutter, requiring knowledge of the gutter size set on the\ngrid. When done manually this can be very brittle, and when using React's\n`context` or `cloneElement`, can cause needless rerenders of _all_ children.\n\nSince CSS custom properties are inherited through the cascade, setting the value\nof the gutter as a **documented** part of the component API, opens it up for\nusage in a descendant component:\n\n```tsx\n// In `Grid.tsx`\nconst GridStyles = s9.create({\n base: {\n --gridColumnGap: '2rem',\n columnGap: 'var(--gridColumnGap)',\n },\n});\n\n// in `Subcomponent.tsx`\nconst SubcomponentStyles = s9.create({\n base: {\n marginInline: 'calc(var(--gridColumnGap) / -2)',\n },\n});\n\n```\n\n### Server State (data)\n\nTODO: Describe [ReactQuery](https://react-query.tanstack.com/) workflow\n\n### Application State\n\nApplication state is currently managed with a mix of `React` context and\n`React.useSate` / `React.useReducer`. See these articles for more details on the\npatterns to use:\n[application-state-management-with-react](https://kentcdodds.com/blog/application-state-management-with-react)\n[how-to-use-react-context-effectively](https://kentcdodds.com/blog/how-to-use-react-context-effectively)\n[how-to-optimize-your-context-value](https://kentcdodds.com/blog/how-to-optimize-your-context-value)\n\nIn the future, and if the need arises, we might consider switching to library\nlike [Jotai](https://jotai.pmnd.rs/) that optimizes around atomic rerenders.\n\n## Development\n\nWe aim to create a streamlined development experience that both enables quick\niteration through types, IDE auto complete, and an automated workflows. At the\nsame time, we are concerned about maintaining code correctness and doing our\nbest to avoid regressions.\n\n### Conformance\n\nWhenever new code is submitted to the codebase, it will be be checked for\ncorrectness. Cheaper processes, like linting and formatting will be run on every\ncommit (for changed files only) to ensure basic standards are upheld. More\nexpensive processes, such as typechecking and tests will be run whenever code is\npushed to remote (again, only on changed files and files related to them,\nwhenever possible).\n\nA full run of all checks will be run on the entire repository in CI, and must\npass before a pull request can be merged (see more below).\n\n#### Chromatic\n\nWe use Chromatic to generate visual snapshots of components and run visual\nregression tests against Storybook stories as part of our CI process. In\nchromatic, we use a feature called\n[TurboSnap](https://www.chromatic.com/docs/turbosnap) (not to be confused with\nTurborepo!), which only takes snapshots of changed components on every build.\nHowever, when making changes that affect the entire system, e.g., changing the\nreset or one of the base colors, there might be a need to retake all the\nsnapshots and make sure there are no regressions.\n\nWith some changes, TurboSnap has no way to \"understand\" that the cache needs to\nbe invalidated in its entirety, meaning we'd have to do it manually. This can be\ndone by editing the `.chromatic-cache-bust.yaml` file and bumping the version\nkey.\n\n### Submitting Code (Pull Requests)\n\nWe use pull requests in GitHub as our process for getting new code to\nproduction.\n\nBy default, pull requests will be opened in `draft` mode. Since some tests are\nexpensive (both in time and in money, when they use third-party services),\nconformance checks will not be run until they are taken out of `draft` mode.\n\nOnce a pull request is taken out of `draft` mode, the full suite of conformance\ntests will be run against it. If the branch includes UI changes, it will also\ninclude visual regression testing in Chromatic, where every change will need to\nbe independently approved.\n\nFor a pull request to be merged, it must be approved by at least one reviewer\nand all checks must pass.\n\nAs a rule of thumb, the best time to take a pull request out of `draft` mode is\nby the reviewer, after making the review and when there are no more request for\nchanges.\n\n## Script and Task-running\n\nDevelopment tasks are run using\n[npm scripts](https://docs.npmjs.com/misc/scripts), using the\n[pnpm](https://pnpm.io/motivation) package manager.\n\nWe use [scripty](https://github.com/testdouble/scripty) in order to avoid\nwriting complex code as string values inside the `package.json` `scripts`\nobject. It allows us the convenience of writing full fledged shell (or node)\nscripts, and offloading more complex logic (what and how to build, etc.) there.\n\nThe path to Scripty scripts is defined in the root `package.json` file, and in\nthat of each package, under `scripty.path`.\n\nGenerally speaking, workspace scripts reside under `scripts/workspace` while\npackage scripts reside under `scripts/packages`.\n\nFor a more detailed overview of how Scripy works, see its\n[documentation](https://github.com/testdouble/scripty).\n\n### Top-Level Scripts\n\nTop level scripts are defined in the to project's root `package.json` file and\nare used to handle project-level tasks.\n\n#### bootstrap\n\nBuild internal packages that must be transpiled before being consumed by other\npackages (e.g., babel macros).\n\n#### build\n\nUses pre-app sub-scripts to build all apps. This is most likely not what you\nwant, and should probably use one of the subscripts directly.\n\n**`build:htz`:** builds the Haaretz.co.il app\n\n#### clean\n\nRemoves all generated artifacts and sets the stage for fresh side-effect free\nbuilds.\n\n#### docs\n\nBuild API docs.\n\n#### format\n\nFormat and lint each workspace package using its own configuration.\nAutomatically automatically fix issues whenever possible.\n\n**`format:check`:** Same as above, but checks formatting correctness without\napplying any changes.\n\n#### code generators\n\nRun generators to scaffold new code\n\n**g:move-package** Handles the entire pipeline of moving or renaming packages,\nfrom changes to Typescript path aliases through updating dependent packages to\nupdating imports.\n\n**g:component** Scaffolds a new UI component package, with test and stories\nfiles.\n\n**g:subcomponent** Scaffolds a subcomponent in an exiting UI component package,\nwith test and stories files, and optionally exposes it as part of the package's\npublic API.\n\n**g:util-package** Scaffolds a new util or hook package, with test and stories\nfiles.\n\n**g:util-package** Scaffolds an individual util or hook in an existing package,\nwith test and stories files, and optionally exposes it as part of the package's\npublic API.\n\n#### test\n\nConcurrently run tests in each package, using its own configuration\n\n#### typecheck\n\nConcurrently check typescript types in each package, using its own configuration\n\n#### CI tasks\n\nTasks with a `:ci` suffix are meant to validate code correctness (lint, test,\ntypecheck, etc.) in CI, and are not meant to be run manually in a local\nenvironment.\n\n## Configuration\n\nWe use the [node-config](https://github.com/node-config/node-config) to manage\nglobal environment-specific variables within applications (E.g., `dev`, `prod`,\n`dev2prod`, etc.).\n\n`node-config` allows us to easily use more complex data structures that would be\nconveniently possible using regular environment variables, and helps us\ndeclutter and simplify the running of commands, which would otherwise require\nthat we pass a handful of variables every time we want to run a simple task.\n\n### Security\n\n> **Warning**\n>\n> Since `node-config` is a server-side module, in the browser we alias the\n> config module to a shim that has access to the serialized output of the real\n> module. Note that **all values in the resulting config are public**\n> information, and are visible to anyone who can look at the html.\n\nTherefore, **sensitive values (session secrets, database passwords, etc.) and\nserver-only concerns should _only ever_ be loaded via environment variables**.\nEnvironment variables are not made public by default, unless explicitly made\npublic in an app's webpack config or `next.config.js` file.\n\n### Usage\n\nBefore starting to use config values, it is a good idea to familiarize yourself\nwith [node-config](https://github.com/node-config/node-config)'s basic concepts\nand how it works.\n\nTo use a config value in your code, first, import the config object:\n\n```ts\nimport config from 'config';\n```\n\nEvery value in the config object is now available to you using the `config.get`\nmethod. You can use the `config.has` method to check for the presence of\noptional values, which are not always defined. Since our configs all typed in\nTypeScript, it should be easy to discern when the usage of `has` is required.\n\n### Configuration Resolving\n\nIn its default configuration, node-config will look for config files in the\nconfig folder of the current (appliaction) working directory. The exact files\nloaded and merged depend on various environment variables, but the most basic\nsetup looks like:\n\n```sh\nconfig\n└── default.js\n```\n\nIf you are writing a reusable library, it’s likely the above is all you need -\nif at all, because the configuration will only be used for your package’s tests\nand storybook. There is usually no need to supply a production configuration in\na library, because when it is imported by an app, that package’s own\nconfiguration will be used.\n\nYou should document any config properties that your modules use, so that\nconsumers know what values their configuration must define.\n\nIf, for example, you want to run tests with some values, but see other values in\nstorybook, you could have:\n\n```sh\nconfig\n├── dev.js\n└── test.js\n```\n\nThe loaded config will be based on the `NODE_ENV` environment variable, which is\n`dev` by default, and `test` when running the test suite. If the `dev` and\n`test` configs share a lot of the same values, then you can additionally have\n`config/default.js`, and the environment configs will contain only overrides.\nSee the node-config\n[Configuration Files](https://github.com/lorenwest/node-config/wiki/Configuration-Files)\ndocs for more details.\n\nIn an app package, you might have even more scenarios:\n\n```sh\nconfig\n├── default.js\n├── dev.js\n├── prod.js\n└── test.js\n```\n\nNote that config values should not change during the execution of an\napplication, only over the lifetime of multiple deployments! In a running app,\nthey should be considered frozen. If you need changing values while the\napplication is running, you should use state, not configuration (although the\ninitial value could be supplied by the config).\n\n### Overriding the Environment preset\n\nSome scenarios, requires you to run your app from one environment, but have it\nconnect to another (i.e. a staging environment that connects to production); For\nthis matter, a `dev.js` configuration will inspect a provided environment\nvariable called `NODE_CONFIG_ENV` which can take the following values: `dev`,\n`dev2pros`, `qa`, `stage` and `prod`. This will start the application with\nanother connection preset, without overriding the value of `NODE_ENV`.\n\n### Secrets\n\nSome configuration values should be kept secure (like session secrets, database\npasswords, etc.), and others are just unnecessary to ship alongside the\napplication code (like configurable absolute file paths, internal IP addresses\nand port numbers, etc.). Since these are almost always just simple strings, and\nthey should be harder to add to the Git repository by mistake, they should be\nkept in environment variables. Setting these variables can be part of the\ndeployment process, or they can be loaded via\n[dotenv](https://www.npmjs.com/package/dotenv), which the Application Server\nwill use automatically. The Git repository will ignore `.env` files by default.\n";var jsx_runtime=__webpack_require__("../../../node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/next/dist/compiled/react/jsx-runtime.js");function _createMdxContent(props){return(0,jsx_runtime.jsxs)(jsx_runtime.Fragment,{children:[(0,jsx_runtime.jsx)(dist.h_,{title:"About"}),"\n",(0,jsx_runtime.jsx)(dist.dk,{children:README_namespaceObject})]})}const __page=()=>{throw new Error("Docs-only story")};__page.parameters={docsOnly:!0};const componentMeta={title:"About",tags:["stories-mdx"],includeStories:["__page"]};componentMeta.parameters=componentMeta.parameters||{},componentMeta.parameters.docs={...componentMeta.parameters.docs||{},page:function MDXContent(props={}){const{wrapper:MDXLayout}=Object.assign({},(0,lib.ah)(),props.components);return MDXLayout?(0,jsx_runtime.jsx)(MDXLayout,{...props,children:(0,jsx_runtime.jsx)(_createMdxContent,{...props})}):_createMdxContent()}};const About_stories=componentMeta}}]);