CINXE.COM

GitHub - ladjs/lad at snyk-fix-bed97d0c625fc25446b4c14528f312d1

<!DOCTYPE html> <html lang="en" data-color-mode="auto" data-light-theme="light" data-dark-theme="dark" data-a11y-animated-images="system" data-a11y-link-underlines="true" > <head> <meta charset="utf-8"> <link rel="dns-prefetch" href="https://github.githubassets.com"> <link rel="dns-prefetch" href="https://avatars.githubusercontent.com"> <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com"> <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/"> <link rel="preconnect" href="https://github.githubassets.com" crossorigin> <link rel="preconnect" href="https://avatars.githubusercontent.com"> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/light-74231a1f3bbb.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/dark-8a995f0bacd4.css" /><link data-color-theme="dark_dimmed" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_dimmed-f37fb7684b1f.css" /><link data-color-theme="dark_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_high_contrast-9ac301c3ebe5.css" /><link data-color-theme="dark_colorblind" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_colorblind-cd826e8636dc.css" /><link data-color-theme="light_colorblind" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_colorblind-f91b0f603451.css" /><link data-color-theme="light_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_high_contrast-83beb16e0ecf.css" /><link data-color-theme="light_tritanopia" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_tritanopia-6e122dab64fc.css" /><link data-color-theme="dark_tritanopia" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_tritanopia-18119e682df0.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-primitives-225433424a87.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-aaa714e5674d.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/global-7eaba1d4847c.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/github-ea73c9cb5377.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/repository-4fce88777fa8.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/code-0210be90f4d3.css" /> <script type="application/json" id="client-env">{"locale":"en","featureFlags":["a11y_quote_reply_fix","copilot_immersive_issue_preview","copilot_new_references_ui","copilot_chat_repo_custom_instructions_preview","copilot_no_floating_button","copilot_topics_as_references","copilot_read_shared_conversation","copilot_duplicate_thread","copilot_buffered_streaming","dotcom_chat_client_side_skills","experimentation_azure_variant_endpoint","failbot_handle_non_errors","fgpat_form_ui_updates","geojson_azure_maps","ghost_pilot_confidence_truncation_25","ghost_pilot_confidence_truncation_40","github_models_o3_mini_streaming","insert_before_patch","issues_react_remove_placeholders","issues_react_blur_item_picker_on_close","marketing_pages_search_explore_provider","primer_react_css_modules_ga","react_data_router_pull_requests","remove_child_patch","sample_network_conn_type","swp_enterprise_contact_form","site_proxima_australia_update","viewscreen_sandbox","issues_react_create_milestone","issues_react_cache_fix_workaround","lifecycle_label_name_updates","copilot_task_oriented_assistive_prompts","issue_types_prevent_private_type_creation","refresh_image_video_src","react_router_dispose_on_disconnect","codespaces_prebuild_region_target_update","turbo_app_id_restore","copilot_code_review_sign_up_closed"]}</script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/wp-runtime-928159a5f506.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_oddbird_popover-polyfill_dist_popover_js-9da652f58479.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_arianotify-polyfill_ariaNotify-polyfill_js-node_modules_github_mi-3abb8f-46b9f4874d95.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_failbot_failbot_ts-75968cfb5298.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/environment-f04cb2a9fc8c.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_primer_behaviors_dist_esm_index_mjs-0dbb79f97f8f.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_selector-observer_dist_index_esm_js-f690fd9ae3d5.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_relative-time-element_dist_index_js-62d275b7ddd9.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_text-expander-element_dist_index_js-78748950cb0c.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_auto-complete-element_dist_index_js-node_modules_github_catalyst_-8e9f78-a90ac05d2469.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_filter-input-element_dist_index_js-node_modules_github_remote-inp-b5f1d7-a1760ffda83d.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_markdown-toolbar-element_dist_index_js-ceef33f593fa.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_file-attachment-element_dist_index_js-node_modules_primer_view-co-c44a69-efa32db3a345.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/github-elements-394f8eb34f19.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/element-registry-8206a1f1fc89.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_braintree_browser-detection_dist_browser-detection_js-node_modules_githu-2906d7-2a07a295af40.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_lit-html_lit-html_js-be8cb88f481b.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_mini-throttle_dist_index_js-node_modules_morphdom_dist_morphdom-e-7c534c-a4a1922eb55f.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_turbo_dist_turbo_es2017-esm_js-a03ee12d659a.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_remote-form_dist_index_js-node_modules_delegated-events_dist_inde-893f9f-b6294cf703b7.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_color-convert_index_js-e3180fe3bcb3.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_quote-selection_dist_index_js-node_modules_github_session-resume_-947061-e7a6c4a19f98.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_updatable-content_updatable-content_ts-2a55124d5c52.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/app_assets_modules_github_behaviors_task-list_ts-app_assets_modules_github_sso_ts-ui_packages-900dde-768abe60b1f8.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/app_assets_modules_github_sticky-scroll-into-view_ts-3e000c5d31a9.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/app_assets_modules_github_behaviors_ajax-error_ts-app_assets_modules_github_behaviors_include-87a4ae-b8865f653f6b.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/app_assets_modules_github_behaviors_commenting_edit_ts-app_assets_modules_github_behaviors_ht-83c235-e429cff6ceb1.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/behaviors-c1f5beceda17.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_delegated-events_dist_index_js-node_modules_github_catalyst_lib_index_js-f6223d90c7ba.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/notifications-global-01e85cd1be94.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_virtualized-list_es_index_js-node_modules_github_template-parts_lib_index_js-94dc7a2157c1.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_remote-form_dist_index_js-node_modules_delegated-events_dist_inde-70450e-4b93df70b903.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/app_assets_modules_github_ref-selector_ts-3e9d848bab5f.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/codespaces-c3bcacfe317c.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_filter-input-element_dist_index_js-node_modules_github_remote-inp-3eebbd-0763620ad7bf.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_mini-throttle_dist_decorators_js-node_modules_delegated-events_di-e161aa-9d41fb1b6c9e.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_file-attachment-element_dist_index_js-node_modules_github_remote--3c9c82-b71ef90fbdc7.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/repositories-7a0dbaa42c57.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_mini-throttle_dist_index_js-node_modules_github_catalyst_lib_inde-dbbea9-26cce2010167.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/code-menu-1c0aedc134b1.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/primer-react-dee7fde768ad.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/react-core-a18127980111.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/react-lib-f1bca44e0926.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/octicons-react-cf2f2ab8dab4.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_emotion_is-prop-valid_dist_emotion-is-prop-valid_esm_js-node_modules_emo-62da9f-2df2f32ec596.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_mini-throttle_dist_index_js-node_modules_stacktrace-parser_dist_s-e7dcdd-9a233856b02c.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_oddbird_popover-polyfill_dist_popover-fn_js-55fea94174bf.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/notifications-subscriptions-menu-58a0c58bfee4.js"></script> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react.2708311ccb5cb34358b1.module.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/notifications-subscriptions-menu.1bcff9205c241e99cff2.module.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react.2708311ccb5cb34358b1.module.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/notifications-subscriptions-menu.1bcff9205c241e99cff2.module.css" /> <title>GitHub - ladjs/lad at snyk-fix-bed97d0c625fc25446b4c14528f312d1</title> <meta name="route-pattern" content="/:user_id/:repository/tree/*name(/*path)" data-turbo-transient> <meta name="route-controller" content="files" data-turbo-transient> <meta name="route-action" content="disambiguate" data-turbo-transient> <meta name="current-catalog-service-hash" content="f3abb0cc802f3d7b95fc8762b94bdcb13bf39634c40c357301c4aa1d67a256fb"> <meta name="request-id" content="ED5C:1F507C:578DB4:69076F:67E4EB3B" data-pjax-transient="true"/><meta name="html-safe-nonce" content="e58508d2ef53a44a53c319506fd9139664375f7285d2bfd3916dc72812873a5d" data-pjax-transient="true"/><meta name="visitor-payload" content="eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFRDVDOjFGNTA3Qzo1NzhEQjQ6NjkwNzZGOjY3RTRFQjNCIiwidmlzaXRvcl9pZCI6IjQ5OTY5NDAxNzEzOTUyNjMyOTEiLCJyZWdpb25fZWRnZSI6InNvdXRoZWFzdGFzaWEiLCJyZWdpb25fcmVuZGVyIjoic291dGhlYXN0YXNpYSJ9" data-pjax-transient="true"/><meta name="visitor-hmac" content="f263a4bf54f931b1b8381a64fc03c6400b5ddbfc8468bcd591082cd520ffb70d" data-pjax-transient="true"/> <meta name="hovercard-subject-tag" content="repository:2791470" data-turbo-transient> <meta name="github-keyboard-shortcuts" content="repository,source-code,file-tree,copilot" data-turbo-transient="true" /> <meta name="selected-link" value="repo_source" data-turbo-transient> <link rel="assets" href="https://github.githubassets.com/"> <meta name="google-site-verification" content="Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I"> <meta name="octolytics-url" content="https://collector.github.com/github/collect" /> <meta name="analytics-location" content="/&lt;user-name&gt;/&lt;repo-name&gt;/files/disambiguate" data-turbo-transient="true" /> <meta name="user-login" content=""> <meta name="viewport" content="width=device-width"> <meta name="description" content="Node.js framework made by a former @expressjs TC and @koajs team member. Built for @forwardemail, @spamscanner, @breejs, @cabinjs, and @lassjs. - GitHub - ladjs/lad at snyk-fix-bed97d0c625fc25446b4c14528f312d1"> <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub"> <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub"> <meta property="fb:app_id" content="1401488693436528"> <meta name="apple-itunes-app" content="app-id=1477376905, app-argument=https://github.com/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1" /> <meta name="twitter:image" content="https://repository-images.githubusercontent.com/2791470/19bfb900-d935-11e9-88e5-52ad10052086" /><meta name="twitter:site" content="@github" /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content="GitHub - ladjs/lad at snyk-fix-bed97d0c625fc25446b4c14528f312d1" /><meta name="twitter:description" content="Node.js framework made by a former @expressjs TC and @koajs team member. Built for @forwardemail, @spamscanner, @breejs, @cabinjs, and @lassjs. - GitHub - ladjs/lad at snyk-fix-bed97d0c625fc25446b4..." /> <meta property="og:image" content="https://repository-images.githubusercontent.com/2791470/19bfb900-d935-11e9-88e5-52ad10052086" /><meta property="og:image:alt" content="Node.js framework made by a former @expressjs TC and @koajs team member. Built for @forwardemail, @spamscanner, @breejs, @cabinjs, and @lassjs. - GitHub - ladjs/lad at snyk-fix-bed97d0c625fc25446b4..." /><meta property="og:site_name" content="GitHub" /><meta property="og:type" content="object" /><meta property="og:title" content="GitHub - ladjs/lad at snyk-fix-bed97d0c625fc25446b4c14528f312d1" /><meta property="og:url" content="https://github.com/ladjs/lad" /><meta property="og:description" content="Node.js framework made by a former @expressjs TC and @koajs team member. Built for @forwardemail, @spamscanner, @breejs, @cabinjs, and @lassjs. - GitHub - ladjs/lad at snyk-fix-bed97d0c625fc25446b4..." /> <meta name="hostname" content="github.com"> <meta name="expected-hostname" content="github.com"> <meta http-equiv="x-pjax-version" content="ca11923418edd975e61fdedf7a77921e13dcbf2f794ef361870092ccabe8c982" data-turbo-track="reload"> <meta http-equiv="x-pjax-csp-version" content="77190eb53eb47fc30bd2fcc17a7eefa2dfd8505869fee9299ba911be3a40a9eb" data-turbo-track="reload"> <meta http-equiv="x-pjax-css-version" content="911af613659f2a8ff08d51fd492330c9e8a6ed8f0c4eb3c6632db43599431d16" data-turbo-track="reload"> <meta http-equiv="x-pjax-js-version" content="9dfb838706fc9f0cc90ef593098cf7b6105c8c3bce7df6533795fc8b7acb8a5b" data-turbo-track="reload"> <meta name="turbo-cache-control" content="no-preview" data-turbo-transient=""> <meta data-hydrostats="publish"> <meta name="go-import" content="github.com/ladjs/lad git https://github.com/ladjs/lad.git"> <meta name="octolytics-dimension-user_id" content="30959108" /><meta name="octolytics-dimension-user_login" content="ladjs" /><meta name="octolytics-dimension-repository_id" content="2791470" /><meta name="octolytics-dimension-repository_nwo" content="ladjs/lad" /><meta name="octolytics-dimension-repository_public" content="true" /><meta name="octolytics-dimension-repository_is_fork" content="false" /><meta name="octolytics-dimension-repository_network_root_id" content="2791470" /><meta name="octolytics-dimension-repository_network_root_nwo" content="ladjs/lad" /> <link rel="canonical" href="https://github.com/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1" data-turbo-transient> <meta name="turbo-body-classes" content="logged-out env-production page-responsive"> <meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats"> <meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors"> <meta name="release" content="edefe724b5cc80cb465d4b6f15cfab44eb312a07"> <link rel="mask-icon" href="https://github.githubassets.com/assets/pinned-octocat-093da3e6fa40.svg" color="#000000"> <link rel="alternate icon" class="js-site-favicon" type="image/png" href="https://github.githubassets.com/favicons/favicon.png"> <link rel="icon" class="js-site-favicon" type="image/svg+xml" href="https://github.githubassets.com/favicons/favicon.svg" data-base-href="https://github.githubassets.com/favicons/favicon"> <meta name="theme-color" content="#1e2327"> <meta name="color-scheme" content="light dark" /> <link rel="manifest" href="/manifest.json" crossOrigin="use-credentials"> </head> <body class="logged-out env-production page-responsive" style="word-wrap: break-word;"> <div data-turbo-body class="logged-out env-production page-responsive" style="word-wrap: break-word;"> <div class="position-relative header-wrapper js-header-wrapper "> <a href="#start-of-content" data-skip-target-assigned="false" class="px-2 py-4 color-bg-accent-emphasis color-fg-on-emphasis show-on-focus js-skip-to-content">Skip to content</a> <span data-view-component="true" class="progress-pjax-loader Progress position-fixed width-full"> <span style="width: 0%;" data-view-component="true" class="Progress-item progress-pjax-loader-bar left-0 top-0 color-bg-accent-emphasis"></span> </span> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_ui-commands_ui-commands_ts-2ea4e93613c0.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/keyboard-shortcuts-dialog-33dfb803e078.js"></script> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react.2708311ccb5cb34358b1.module.css" /> <react-partial partial-name="keyboard-shortcuts-dialog" data-ssr="false" data-attempted-ssr="false" > <script type="application/json" data-target="react-partial.embeddedData">{"props":{"docsUrl":"https://docs.github.com/get-started/accessibility/keyboard-shortcuts"}}</script> <div data-target="react-partial.reactRoot"></div> </react-partial> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_github_remote-form_dist_index_js-node_modules_delegated-events_dist_inde-94fd67-4898d1bf4b51.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/sessions-730dca81d0a2.js"></script> <header class="HeaderMktg header-logged-out js-details-container js-header Details f4 py-3" role="banner" data-is-top="true" data-color-mode=light data-light-theme=light data-dark-theme=dark> <h2 class="sr-only">Navigation Menu</h2> <button type="button" class="HeaderMktg-backdrop d-lg-none border-0 position-fixed top-0 left-0 width-full height-full js-details-target" aria-label="Toggle navigation"> <span class="d-none">Toggle navigation</span> </button> <div class="d-flex flex-column flex-lg-row flex-items-center px-3 px-md-4 px-lg-5 height-full position-relative z-1"> <div class="d-flex flex-justify-between flex-items-center width-full width-lg-auto"> <div class="flex-1"> <button aria-label="Toggle navigation" aria-expanded="false" type="button" data-view-component="true" class="js-details-target js-nav-padding-recalculate js-header-menu-toggle Button--link Button--medium Button d-lg-none color-fg-inherit p-1"> <span class="Button-content"> <span class="Button-label"><div class="HeaderMenu-toggle-bar rounded my-1"></div> <div class="HeaderMenu-toggle-bar rounded my-1"></div> <div class="HeaderMenu-toggle-bar rounded my-1"></div></span> </span> </button> </div> <a class="mr-lg-3 color-fg-inherit flex-order-2 js-prevent-focus-on-mobile-nav" href="/" aria-label="Homepage" data-analytics-event="{&quot;category&quot;:&quot;Marketing nav&quot;,&quot;action&quot;:&quot;click to go to homepage&quot;,&quot;label&quot;:&quot;ref_page:Marketing;ref_cta:Logomark;ref_loc:Header&quot;}"> <svg height="32" aria-hidden="true" viewBox="0 0 24 24" version="1.1" width="32" data-view-component="true" class="octicon octicon-mark-github"> <path d="M12 1C5.9225 1 1 5.9225 1 12C1 16.8675 4.14875 20.9787 8.52125 22.4362C9.07125 22.5325 9.2775 22.2025 9.2775 21.9137C9.2775 21.6525 9.26375 20.7862 9.26375 19.865C6.5 20.3737 5.785 19.1912 5.565 18.5725C5.44125 18.2562 4.905 17.28 4.4375 17.0187C4.0525 16.8125 3.5025 16.3037 4.42375 16.29C5.29 16.2762 5.90875 17.0875 6.115 17.4175C7.105 19.0812 8.68625 18.6137 9.31875 18.325C9.415 17.61 9.70375 17.1287 10.02 16.8537C7.5725 16.5787 5.015 15.63 5.015 11.4225C5.015 10.2262 5.44125 9.23625 6.1425 8.46625C6.0325 8.19125 5.6475 7.06375 6.2525 5.55125C6.2525 5.55125 7.17375 5.2625 9.2775 6.67875C10.1575 6.43125 11.0925 6.3075 12.0275 6.3075C12.9625 6.3075 13.8975 6.43125 14.7775 6.67875C16.8813 5.24875 17.8025 5.55125 17.8025 5.55125C18.4075 7.06375 18.0225 8.19125 17.9125 8.46625C18.6138 9.23625 19.04 10.2125 19.04 11.4225C19.04 15.6437 16.4688 16.5787 14.0213 16.8537C14.42 17.1975 14.7638 17.8575 14.7638 18.8887C14.7638 20.36 14.75 21.5425 14.75 21.9137C14.75 22.2025 14.9563 22.5462 15.5063 22.4362C19.8513 20.9787 23 16.8537 23 12C23 5.9225 18.0775 1 12 1Z"></path> </svg> </a> <div class="flex-1 flex-order-2 text-right"> <a href="/login?return_to=https%3A%2F%2Fgithub.com%2Fladjs%2Flad%2Ftree%2Fsnyk-fix-bed97d0c625fc25446b4c14528f312d1" class="HeaderMenu-link HeaderMenu-button d-inline-flex d-lg-none flex-order-1 f5 no-underline border color-border-default rounded-2 px-2 py-1 color-fg-inherit js-prevent-focus-on-mobile-nav" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="e408f48c644ef4427d1b27f1859d43c18428f63e1c5ff1e4b406da79e135a1db" data-analytics-event="{&quot;category&quot;:&quot;Marketing nav&quot;,&quot;action&quot;:&quot;click to Sign in&quot;,&quot;label&quot;:&quot;ref_page:Marketing;ref_cta:Sign in;ref_loc:Header&quot;}" > Sign in </a> </div> </div> <div class="HeaderMenu js-header-menu height-fit position-lg-relative d-lg-flex flex-column flex-auto top-0"> <div class="HeaderMenu-wrapper d-flex flex-column flex-self-start flex-lg-row flex-auto rounded rounded-lg-0"> <nav class="HeaderMenu-nav" aria-label="Global"> <ul class="d-lg-flex list-style-none"> <li class="HeaderMenu-item position-relative flex-wrap flex-justify-between flex-items-center d-block d-lg-flex flex-lg-nowrap flex-lg-items-center js-details-container js-header-menu-item"> <button type="button" class="HeaderMenu-link border-0 width-full width-lg-auto px-0 px-lg-2 py-lg-2 no-wrap d-flex flex-items-center flex-justify-between js-details-target" aria-expanded="false"> Product <svg opacity="0.5" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-chevron-down HeaderMenu-icon ml-1"> <path d="M12.78 5.22a.749.749 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.06 0L3.22 6.28a.749.749 0 1 1 1.06-1.06L8 8.939l3.72-3.719a.749.749 0 0 1 1.06 0Z"></path> </svg> </button> <div class="HeaderMenu-dropdown dropdown-menu rounded m-0 p-0 pt-2 pt-lg-4 position-relative position-lg-absolute left-0 left-lg-n3 pb-2 pb-lg-4 d-lg-flex flex-wrap dropdown-menu-wide"> <div class="HeaderMenu-column px-lg-4 border-lg-right mb-4 mb-lg-0 pr-lg-7"> <div class="border-bottom pb-3 pb-lg-0 border-lg-bottom-0"> <ul class="list-style-none f5" > <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;github_copilot&quot;,&quot;context&quot;:&quot;product&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;github_copilot_link_product_navbar&quot;}" href="https://github.com/features/copilot"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-copilot color-fg-subtle mr-3"> <path d="M23.922 16.992c-.861 1.495-5.859 5.023-11.922 5.023-6.063 0-11.061-3.528-11.922-5.023A.641.641 0 0 1 0 16.736v-2.869a.841.841 0 0 1 .053-.22c.372-.935 1.347-2.292 2.605-2.656.167-.429.414-1.055.644-1.517a10.195 10.195 0 0 1-.052-1.086c0-1.331.282-2.499 1.132-3.368.397-.406.89-.717 1.474-.952 1.399-1.136 3.392-2.093 6.122-2.093 2.731 0 4.767.957 6.166 2.093.584.235 1.077.546 1.474.952.85.869 1.132 2.037 1.132 3.368 0 .368-.014.733-.052 1.086.23.462.477 1.088.644 1.517 1.258.364 2.233 1.721 2.605 2.656a.832.832 0 0 1 .053.22v2.869a.641.641 0 0 1-.078.256ZM12.172 11h-.344a4.323 4.323 0 0 1-.355.508C10.703 12.455 9.555 13 7.965 13c-1.725 0-2.989-.359-3.782-1.259a2.005 2.005 0 0 1-.085-.104L4 11.741v6.585c1.435.779 4.514 2.179 8 2.179 3.486 0 6.565-1.4 8-2.179v-6.585l-.098-.104s-.033.045-.085.104c-.793.9-2.057 1.259-3.782 1.259-1.59 0-2.738-.545-3.508-1.492a4.323 4.323 0 0 1-.355-.508h-.016.016Zm.641-2.935c.136 1.057.403 1.913.878 2.497.442.544 1.134.938 2.344.938 1.573 0 2.292-.337 2.657-.751.384-.435.558-1.15.558-2.361 0-1.14-.243-1.847-.705-2.319-.477-.488-1.319-.862-2.824-1.025-1.487-.161-2.192.138-2.533.529-.269.307-.437.808-.438 1.578v.021c0 .265.021.562.063.893Zm-1.626 0c.042-.331.063-.628.063-.894v-.02c-.001-.77-.169-1.271-.438-1.578-.341-.391-1.046-.69-2.533-.529-1.505.163-2.347.537-2.824 1.025-.462.472-.705 1.179-.705 2.319 0 1.211.175 1.926.558 2.361.365.414 1.084.751 2.657.751 1.21 0 1.902-.394 2.344-.938.475-.584.742-1.44.878-2.497Z"></path><path d="M14.5 14.25a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0v-2a1 1 0 0 1 1-1Zm-5 0a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0v-2a1 1 0 0 1 1-1Z"></path> </svg> <div> <div class="color-fg-default h4">GitHub Copilot</div> Write better code with AI </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;security&quot;,&quot;context&quot;:&quot;product&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;security_link_product_navbar&quot;}" href="https://github.com/features/security"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-shield-check color-fg-subtle mr-3"> <path d="M16.53 9.78a.75.75 0 0 0-1.06-1.06L11 13.19l-1.97-1.97a.75.75 0 0 0-1.06 1.06l2.5 2.5a.75.75 0 0 0 1.06 0l5-5Z"></path><path d="m12.54.637 8.25 2.675A1.75 1.75 0 0 1 22 4.976V10c0 6.19-3.771 10.704-9.401 12.83a1.704 1.704 0 0 1-1.198 0C5.77 20.705 2 16.19 2 10V4.976c0-.758.489-1.43 1.21-1.664L11.46.637a1.748 1.748 0 0 1 1.08 0Zm-.617 1.426-8.25 2.676a.249.249 0 0 0-.173.237V10c0 5.46 3.28 9.483 8.43 11.426a.199.199 0 0 0 .14 0C17.22 19.483 20.5 15.461 20.5 10V4.976a.25.25 0 0 0-.173-.237l-8.25-2.676a.253.253 0 0 0-.154 0Z"></path> </svg> <div> <div class="color-fg-default h4">Security</div> Find and fix vulnerabilities </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;actions&quot;,&quot;context&quot;:&quot;product&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;actions_link_product_navbar&quot;}" href="https://github.com/features/actions"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-workflow color-fg-subtle mr-3"> <path d="M1 3a2 2 0 0 1 2-2h6.5a2 2 0 0 1 2 2v6.5a2 2 0 0 1-2 2H7v4.063C7 16.355 7.644 17 8.438 17H12.5v-2.5a2 2 0 0 1 2-2H21a2 2 0 0 1 2 2V21a2 2 0 0 1-2 2h-6.5a2 2 0 0 1-2-2v-2.5H8.437A2.939 2.939 0 0 1 5.5 15.562V11.5H3a2 2 0 0 1-2-2Zm2-.5a.5.5 0 0 0-.5.5v6.5a.5.5 0 0 0 .5.5h6.5a.5.5 0 0 0 .5-.5V3a.5.5 0 0 0-.5-.5ZM14.5 14a.5.5 0 0 0-.5.5V21a.5.5 0 0 0 .5.5H21a.5.5 0 0 0 .5-.5v-6.5a.5.5 0 0 0-.5-.5Z"></path> </svg> <div> <div class="color-fg-default h4">Actions</div> Automate any workflow </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;codespaces&quot;,&quot;context&quot;:&quot;product&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;codespaces_link_product_navbar&quot;}" href="https://github.com/features/codespaces"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-codespaces color-fg-subtle mr-3"> <path d="M3.5 3.75C3.5 2.784 4.284 2 5.25 2h13.5c.966 0 1.75.784 1.75 1.75v7.5A1.75 1.75 0 0 1 18.75 13H5.25a1.75 1.75 0 0 1-1.75-1.75Zm-2 12c0-.966.784-1.75 1.75-1.75h17.5c.966 0 1.75.784 1.75 1.75v4a1.75 1.75 0 0 1-1.75 1.75H3.25a1.75 1.75 0 0 1-1.75-1.75ZM5.25 3.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h13.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Zm-2 12a.25.25 0 0 0-.25.25v4c0 .138.112.25.25.25h17.5a.25.25 0 0 0 .25-.25v-4a.25.25 0 0 0-.25-.25Z"></path><path d="M10 17.75a.75.75 0 0 1 .75-.75h6.5a.75.75 0 0 1 0 1.5h-6.5a.75.75 0 0 1-.75-.75Zm-4 0a.75.75 0 0 1 .75-.75h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1-.75-.75Z"></path> </svg> <div> <div class="color-fg-default h4">Codespaces</div> Instant dev environments </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;issues&quot;,&quot;context&quot;:&quot;product&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;issues_link_product_navbar&quot;}" href="https://github.com/features/issues"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-issue-opened color-fg-subtle mr-3"> <path d="M12 1c6.075 0 11 4.925 11 11s-4.925 11-11 11S1 18.075 1 12 5.925 1 12 1ZM2.5 12a9.5 9.5 0 0 0 9.5 9.5 9.5 9.5 0 0 0 9.5-9.5A9.5 9.5 0 0 0 12 2.5 9.5 9.5 0 0 0 2.5 12Zm9.5 2a2 2 0 1 1-.001-3.999A2 2 0 0 1 12 14Z"></path> </svg> <div> <div class="color-fg-default h4">Issues</div> Plan and track work </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;code_review&quot;,&quot;context&quot;:&quot;product&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;code_review_link_product_navbar&quot;}" href="https://github.com/features/code-review"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-code-review color-fg-subtle mr-3"> <path d="M10.3 6.74a.75.75 0 0 1-.04 1.06l-2.908 2.7 2.908 2.7a.75.75 0 1 1-1.02 1.1l-3.5-3.25a.75.75 0 0 1 0-1.1l3.5-3.25a.75.75 0 0 1 1.06.04Zm3.44 1.06a.75.75 0 1 1 1.02-1.1l3.5 3.25a.75.75 0 0 1 0 1.1l-3.5 3.25a.75.75 0 1 1-1.02-1.1l2.908-2.7-2.908-2.7Z"></path><path d="M1.5 4.25c0-.966.784-1.75 1.75-1.75h17.5c.966 0 1.75.784 1.75 1.75v12.5a1.75 1.75 0 0 1-1.75 1.75h-9.69l-3.573 3.573A1.458 1.458 0 0 1 5 21.043V18.5H3.25a1.75 1.75 0 0 1-1.75-1.75ZM3.25 4a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h2.5a.75.75 0 0 1 .75.75v3.19l3.72-3.72a.749.749 0 0 1 .53-.22h10a.25.25 0 0 0 .25-.25V4.25a.25.25 0 0 0-.25-.25Z"></path> </svg> <div> <div class="color-fg-default h4">Code Review</div> Manage code changes </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;discussions&quot;,&quot;context&quot;:&quot;product&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;discussions_link_product_navbar&quot;}" href="https://github.com/features/discussions"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-comment-discussion color-fg-subtle mr-3"> <path d="M1.75 1h12.5c.966 0 1.75.784 1.75 1.75v9.5A1.75 1.75 0 0 1 14.25 14H8.061l-2.574 2.573A1.458 1.458 0 0 1 3 15.543V14H1.75A1.75 1.75 0 0 1 0 12.25v-9.5C0 1.784.784 1 1.75 1ZM1.5 2.75v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25Z"></path><path d="M22.5 8.75a.25.25 0 0 0-.25-.25h-3.5a.75.75 0 0 1 0-1.5h3.5c.966 0 1.75.784 1.75 1.75v9.5A1.75 1.75 0 0 1 22.25 20H21v1.543a1.457 1.457 0 0 1-2.487 1.03L15.939 20H10.75A1.75 1.75 0 0 1 9 18.25v-1.465a.75.75 0 0 1 1.5 0v1.465c0 .138.112.25.25.25h5.5a.75.75 0 0 1 .53.22l2.72 2.72v-2.19a.75.75 0 0 1 .75-.75h2a.25.25 0 0 0 .25-.25v-9.5Z"></path> </svg> <div> <div class="color-fg-default h4">Discussions</div> Collaborate outside of code </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;code_search&quot;,&quot;context&quot;:&quot;product&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;code_search_link_product_navbar&quot;}" href="https://github.com/features/code-search"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-code-square color-fg-subtle mr-3"> <path d="M10.3 8.24a.75.75 0 0 1-.04 1.06L7.352 12l2.908 2.7a.75.75 0 1 1-1.02 1.1l-3.5-3.25a.75.75 0 0 1 0-1.1l3.5-3.25a.75.75 0 0 1 1.06.04Zm3.44 1.06a.75.75 0 1 1 1.02-1.1l3.5 3.25a.75.75 0 0 1 0 1.1l-3.5 3.25a.75.75 0 1 1-1.02-1.1l2.908-2.7-2.908-2.7Z"></path><path d="M2 3.75C2 2.784 2.784 2 3.75 2h16.5c.966 0 1.75.784 1.75 1.75v16.5A1.75 1.75 0 0 1 20.25 22H3.75A1.75 1.75 0 0 1 2 20.25Zm1.75-.25a.25.25 0 0 0-.25.25v16.5c0 .138.112.25.25.25h16.5a.25.25 0 0 0 .25-.25V3.75a.25.25 0 0 0-.25-.25Z"></path> </svg> <div> <div class="color-fg-default h4">Code Search</div> Find more, search less </div> </a></li> </ul> </div> </div> <div class="HeaderMenu-column px-lg-4"> <div class="border-bottom pb-3 pb-lg-0 border-lg-bottom-0 border-bottom-0"> <span class="d-block h4 color-fg-default my-1" id="product-explore-heading">Explore</span> <ul class="list-style-none f5" aria-labelledby="product-explore-heading"> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;all_features&quot;,&quot;context&quot;:&quot;product&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;all_features_link_product_navbar&quot;}" href="https://github.com/features"> All features </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary Link--external" target="_blank" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;documentation&quot;,&quot;context&quot;:&quot;product&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;documentation_link_product_navbar&quot;}" href="https://docs.github.com"> Documentation <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-link-external HeaderMenu-external-icon color-fg-subtle"> <path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path> </svg> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary Link--external" target="_blank" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;github_skills&quot;,&quot;context&quot;:&quot;product&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;github_skills_link_product_navbar&quot;}" href="https://skills.github.com"> GitHub Skills <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-link-external HeaderMenu-external-icon color-fg-subtle"> <path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path> </svg> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary Link--external" target="_blank" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;blog&quot;,&quot;context&quot;:&quot;product&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;blog_link_product_navbar&quot;}" href="https://github.blog"> Blog <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-link-external HeaderMenu-external-icon color-fg-subtle"> <path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path> </svg> </a></li> </ul> </div> </div> </div> </li> <li class="HeaderMenu-item position-relative flex-wrap flex-justify-between flex-items-center d-block d-lg-flex flex-lg-nowrap flex-lg-items-center js-details-container js-header-menu-item"> <button type="button" class="HeaderMenu-link border-0 width-full width-lg-auto px-0 px-lg-2 py-lg-2 no-wrap d-flex flex-items-center flex-justify-between js-details-target" aria-expanded="false"> Solutions <svg opacity="0.5" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-chevron-down HeaderMenu-icon ml-1"> <path d="M12.78 5.22a.749.749 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.06 0L3.22 6.28a.749.749 0 1 1 1.06-1.06L8 8.939l3.72-3.719a.749.749 0 0 1 1.06 0Z"></path> </svg> </button> <div class="HeaderMenu-dropdown dropdown-menu rounded m-0 p-0 pt-2 pt-lg-4 position-relative position-lg-absolute left-0 left-lg-n3 d-lg-flex flex-wrap dropdown-menu-wide"> <div class="HeaderMenu-column px-lg-4 border-lg-right mb-4 mb-lg-0 pr-lg-7"> <div class="border-bottom pb-3 pb-lg-0 border-lg-bottom-0 pb-lg-3 mb-3 mb-lg-0"> <span class="d-block h4 color-fg-default my-1" id="solutions-by-company-size-heading">By company size</span> <ul class="list-style-none f5" aria-labelledby="solutions-by-company-size-heading"> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;enterprises&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;enterprises_link_solutions_navbar&quot;}" href="https://github.com/enterprise"> Enterprises </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;small_and_medium_teams&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;small_and_medium_teams_link_solutions_navbar&quot;}" href="https://github.com/team"> Small and medium teams </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;startups&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;startups_link_solutions_navbar&quot;}" href="https://github.com/enterprise/startups"> Startups </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;nonprofits&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;nonprofits_link_solutions_navbar&quot;}" href="/solutions/industry/nonprofits"> Nonprofits </a></li> </ul> </div> <div class="border-bottom pb-3 pb-lg-0 border-lg-bottom-0"> <span class="d-block h4 color-fg-default my-1" id="solutions-by-use-case-heading">By use case</span> <ul class="list-style-none f5" aria-labelledby="solutions-by-use-case-heading"> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;devsecops&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;devsecops_link_solutions_navbar&quot;}" href="/solutions/use-case/devsecops"> DevSecOps </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;devops&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;devops_link_solutions_navbar&quot;}" href="/solutions/use-case/devops"> DevOps </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;ci_cd&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;ci_cd_link_solutions_navbar&quot;}" href="/solutions/use-case/ci-cd"> CI/CD </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;view_all_use_cases&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;view_all_use_cases_link_solutions_navbar&quot;}" href="/solutions/use-case"> View all use cases </a></li> </ul> </div> </div> <div class="HeaderMenu-column px-lg-4"> <div class="border-bottom pb-3 pb-lg-0 border-lg-bottom-0"> <span class="d-block h4 color-fg-default my-1" id="solutions-by-industry-heading">By industry</span> <ul class="list-style-none f5" aria-labelledby="solutions-by-industry-heading"> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;healthcare&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;healthcare_link_solutions_navbar&quot;}" href="/solutions/industry/healthcare"> Healthcare </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;financial_services&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;financial_services_link_solutions_navbar&quot;}" href="/solutions/industry/financial-services"> Financial services </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;manufacturing&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;manufacturing_link_solutions_navbar&quot;}" href="/solutions/industry/manufacturing"> Manufacturing </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;government&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;government_link_solutions_navbar&quot;}" href="/solutions/industry/government"> Government </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;view_all_industries&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;view_all_industries_link_solutions_navbar&quot;}" href="/solutions/industry"> View all industries </a></li> </ul> </div> </div> <div class="HeaderMenu-trailing-link rounded-bottom-2 flex-shrink-0 mt-lg-4 px-lg-4 py-4 py-lg-3 f5 text-semibold"> <a href="/solutions"> View all solutions <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-chevron-right HeaderMenu-trailing-link-icon"> <path d="M6.22 3.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L9.94 8 6.22 4.28a.75.75 0 0 1 0-1.06Z"></path> </svg> </a> </div> </div> </li> <li class="HeaderMenu-item position-relative flex-wrap flex-justify-between flex-items-center d-block d-lg-flex flex-lg-nowrap flex-lg-items-center js-details-container js-header-menu-item"> <button type="button" class="HeaderMenu-link border-0 width-full width-lg-auto px-0 px-lg-2 py-lg-2 no-wrap d-flex flex-items-center flex-justify-between js-details-target" aria-expanded="false"> Resources <svg opacity="0.5" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-chevron-down HeaderMenu-icon ml-1"> <path d="M12.78 5.22a.749.749 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.06 0L3.22 6.28a.749.749 0 1 1 1.06-1.06L8 8.939l3.72-3.719a.749.749 0 0 1 1.06 0Z"></path> </svg> </button> <div class="HeaderMenu-dropdown dropdown-menu rounded m-0 p-0 pt-2 pt-lg-4 position-relative position-lg-absolute left-0 left-lg-n3 pb-2 pb-lg-4 d-lg-flex flex-wrap dropdown-menu-wide"> <div class="HeaderMenu-column px-lg-4 border-lg-right mb-4 mb-lg-0 pr-lg-7"> <div class="border-bottom pb-3 pb-lg-0 border-lg-bottom-0"> <span class="d-block h4 color-fg-default my-1" id="resources-topics-heading">Topics</span> <ul class="list-style-none f5" aria-labelledby="resources-topics-heading"> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;ai&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;ai_link_resources_navbar&quot;}" href="/resources/articles/ai"> AI </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;devops&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;devops_link_resources_navbar&quot;}" href="/resources/articles/devops"> DevOps </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;security&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;security_link_resources_navbar&quot;}" href="/resources/articles/security"> Security </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;software_development&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;software_development_link_resources_navbar&quot;}" href="/resources/articles/software-development"> Software Development </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;view_all&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;view_all_link_resources_navbar&quot;}" href="/resources/articles"> View all </a></li> </ul> </div> </div> <div class="HeaderMenu-column px-lg-4"> <div class="border-bottom pb-3 pb-lg-0 border-lg-bottom-0 border-bottom-0"> <span class="d-block h4 color-fg-default my-1" id="resources-explore-heading">Explore</span> <ul class="list-style-none f5" aria-labelledby="resources-explore-heading"> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary Link--external" target="_blank" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;learning_pathways&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;learning_pathways_link_resources_navbar&quot;}" href="https://resources.github.com/learn/pathways"> Learning Pathways <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-link-external HeaderMenu-external-icon color-fg-subtle"> <path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path> </svg> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary Link--external" target="_blank" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;events_amp_webinars&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;events_amp_webinars_link_resources_navbar&quot;}" href="https://resources.github.com"> Events &amp; Webinars <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-link-external HeaderMenu-external-icon color-fg-subtle"> <path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path> </svg> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;ebooks_amp_whitepapers&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;ebooks_amp_whitepapers_link_resources_navbar&quot;}" href="https://github.com/resources/whitepapers"> Ebooks &amp; Whitepapers </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;customer_stories&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;customer_stories_link_resources_navbar&quot;}" href="https://github.com/customer-stories"> Customer Stories </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary Link--external" target="_blank" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;partners&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;partners_link_resources_navbar&quot;}" href="https://partner.github.com"> Partners <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-link-external HeaderMenu-external-icon color-fg-subtle"> <path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path> </svg> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;executive_insights&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;executive_insights_link_resources_navbar&quot;}" href="https://github.com/solutions/executive-insights"> Executive Insights </a></li> </ul> </div> </div> </div> </li> <li class="HeaderMenu-item position-relative flex-wrap flex-justify-between flex-items-center d-block d-lg-flex flex-lg-nowrap flex-lg-items-center js-details-container js-header-menu-item"> <button type="button" class="HeaderMenu-link border-0 width-full width-lg-auto px-0 px-lg-2 py-lg-2 no-wrap d-flex flex-items-center flex-justify-between js-details-target" aria-expanded="false"> Open Source <svg opacity="0.5" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-chevron-down HeaderMenu-icon ml-1"> <path d="M12.78 5.22a.749.749 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.06 0L3.22 6.28a.749.749 0 1 1 1.06-1.06L8 8.939l3.72-3.719a.749.749 0 0 1 1.06 0Z"></path> </svg> </button> <div class="HeaderMenu-dropdown dropdown-menu rounded m-0 p-0 pt-2 pt-lg-4 position-relative position-lg-absolute left-0 left-lg-n3 pb-2 pb-lg-4 px-lg-4"> <div class="HeaderMenu-column"> <div class="border-bottom pb-3 pb-lg-0 pb-lg-3 mb-3 mb-lg-0 mb-lg-3"> <ul class="list-style-none f5" > <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;github_sponsors&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;github_sponsors_link_open_source_navbar&quot;}" href="/sponsors"> <div> <div class="color-fg-default h4">GitHub Sponsors</div> Fund open source developers </div> </a></li> </ul> </div> <div class="border-bottom pb-3 pb-lg-0 pb-lg-3 mb-3 mb-lg-0 mb-lg-3"> <ul class="list-style-none f5" > <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;the_readme_project&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;the_readme_project_link_open_source_navbar&quot;}" href="https://github.com/readme"> <div> <div class="color-fg-default h4">The ReadME Project</div> GitHub community articles </div> </a></li> </ul> </div> <div class="border-bottom pb-3 pb-lg-0 border-bottom-0"> <span class="d-block h4 color-fg-default my-1" id="open-source-repositories-heading">Repositories</span> <ul class="list-style-none f5" aria-labelledby="open-source-repositories-heading"> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;topics&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;topics_link_open_source_navbar&quot;}" href="https://github.com/topics"> Topics </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;trending&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;trending_link_open_source_navbar&quot;}" href="https://github.com/trending"> Trending </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;collections&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;collections_link_open_source_navbar&quot;}" href="https://github.com/collections"> Collections </a></li> </ul> </div> </div> </div> </li> <li class="HeaderMenu-item position-relative flex-wrap flex-justify-between flex-items-center d-block d-lg-flex flex-lg-nowrap flex-lg-items-center js-details-container js-header-menu-item"> <button type="button" class="HeaderMenu-link border-0 width-full width-lg-auto px-0 px-lg-2 py-lg-2 no-wrap d-flex flex-items-center flex-justify-between js-details-target" aria-expanded="false"> Enterprise <svg opacity="0.5" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-chevron-down HeaderMenu-icon ml-1"> <path d="M12.78 5.22a.749.749 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.06 0L3.22 6.28a.749.749 0 1 1 1.06-1.06L8 8.939l3.72-3.719a.749.749 0 0 1 1.06 0Z"></path> </svg> </button> <div class="HeaderMenu-dropdown dropdown-menu rounded m-0 p-0 pt-2 pt-lg-4 position-relative position-lg-absolute left-0 left-lg-n3 pb-2 pb-lg-4 px-lg-4"> <div class="HeaderMenu-column"> <div class="border-bottom pb-3 pb-lg-0 pb-lg-3 mb-3 mb-lg-0 mb-lg-3"> <ul class="list-style-none f5" > <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;enterprise_platform&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;enterprise_platform_link_enterprise_navbar&quot;}" href="/enterprise"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-stack color-fg-subtle mr-3"> <path d="M11.063 1.456a1.749 1.749 0 0 1 1.874 0l8.383 5.316a1.751 1.751 0 0 1 0 2.956l-8.383 5.316a1.749 1.749 0 0 1-1.874 0L2.68 9.728a1.751 1.751 0 0 1 0-2.956Zm1.071 1.267a.25.25 0 0 0-.268 0L3.483 8.039a.25.25 0 0 0 0 .422l8.383 5.316a.25.25 0 0 0 .268 0l8.383-5.316a.25.25 0 0 0 0-.422Z"></path><path d="M1.867 12.324a.75.75 0 0 1 1.035-.232l8.964 5.685a.25.25 0 0 0 .268 0l8.964-5.685a.75.75 0 0 1 .804 1.267l-8.965 5.685a1.749 1.749 0 0 1-1.874 0l-8.965-5.685a.75.75 0 0 1-.231-1.035Z"></path><path d="M1.867 16.324a.75.75 0 0 1 1.035-.232l8.964 5.685a.25.25 0 0 0 .268 0l8.964-5.685a.75.75 0 0 1 .804 1.267l-8.965 5.685a1.749 1.749 0 0 1-1.874 0l-8.965-5.685a.75.75 0 0 1-.231-1.035Z"></path> </svg> <div> <div class="color-fg-default h4">Enterprise platform</div> AI-powered developer platform </div> </a></li> </ul> </div> <div class="border-bottom pb-3 pb-lg-0 border-bottom-0"> <span class="d-block h4 color-fg-default my-1" id="enterprise-available-add-ons-heading">Available add-ons</span> <ul class="list-style-none f5" aria-labelledby="enterprise-available-add-ons-heading"> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;advanced_security&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;advanced_security_link_enterprise_navbar&quot;}" href="https://github.com/enterprise/advanced-security"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-shield-check color-fg-subtle mr-3"> <path d="M16.53 9.78a.75.75 0 0 0-1.06-1.06L11 13.19l-1.97-1.97a.75.75 0 0 0-1.06 1.06l2.5 2.5a.75.75 0 0 0 1.06 0l5-5Z"></path><path d="m12.54.637 8.25 2.675A1.75 1.75 0 0 1 22 4.976V10c0 6.19-3.771 10.704-9.401 12.83a1.704 1.704 0 0 1-1.198 0C5.77 20.705 2 16.19 2 10V4.976c0-.758.489-1.43 1.21-1.664L11.46.637a1.748 1.748 0 0 1 1.08 0Zm-.617 1.426-8.25 2.676a.249.249 0 0 0-.173.237V10c0 5.46 3.28 9.483 8.43 11.426a.199.199 0 0 0 .14 0C17.22 19.483 20.5 15.461 20.5 10V4.976a.25.25 0 0 0-.173-.237l-8.25-2.676a.253.253 0 0 0-.154 0Z"></path> </svg> <div> <div class="color-fg-default h4">Advanced Security</div> Enterprise-grade security features </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description pb-lg-3" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;copilot_for_business&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;copilot_for_business_link_enterprise_navbar&quot;}" href="/features/copilot/copilot-business"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-copilot color-fg-subtle mr-3"> <path d="M23.922 16.992c-.861 1.495-5.859 5.023-11.922 5.023-6.063 0-11.061-3.528-11.922-5.023A.641.641 0 0 1 0 16.736v-2.869a.841.841 0 0 1 .053-.22c.372-.935 1.347-2.292 2.605-2.656.167-.429.414-1.055.644-1.517a10.195 10.195 0 0 1-.052-1.086c0-1.331.282-2.499 1.132-3.368.397-.406.89-.717 1.474-.952 1.399-1.136 3.392-2.093 6.122-2.093 2.731 0 4.767.957 6.166 2.093.584.235 1.077.546 1.474.952.85.869 1.132 2.037 1.132 3.368 0 .368-.014.733-.052 1.086.23.462.477 1.088.644 1.517 1.258.364 2.233 1.721 2.605 2.656a.832.832 0 0 1 .053.22v2.869a.641.641 0 0 1-.078.256ZM12.172 11h-.344a4.323 4.323 0 0 1-.355.508C10.703 12.455 9.555 13 7.965 13c-1.725 0-2.989-.359-3.782-1.259a2.005 2.005 0 0 1-.085-.104L4 11.741v6.585c1.435.779 4.514 2.179 8 2.179 3.486 0 6.565-1.4 8-2.179v-6.585l-.098-.104s-.033.045-.085.104c-.793.9-2.057 1.259-3.782 1.259-1.59 0-2.738-.545-3.508-1.492a4.323 4.323 0 0 1-.355-.508h-.016.016Zm.641-2.935c.136 1.057.403 1.913.878 2.497.442.544 1.134.938 2.344.938 1.573 0 2.292-.337 2.657-.751.384-.435.558-1.15.558-2.361 0-1.14-.243-1.847-.705-2.319-.477-.488-1.319-.862-2.824-1.025-1.487-.161-2.192.138-2.533.529-.269.307-.437.808-.438 1.578v.021c0 .265.021.562.063.893Zm-1.626 0c.042-.331.063-.628.063-.894v-.02c-.001-.77-.169-1.271-.438-1.578-.341-.391-1.046-.69-2.533-.529-1.505.163-2.347.537-2.824 1.025-.462.472-.705 1.179-.705 2.319 0 1.211.175 1.926.558 2.361.365.414 1.084.751 2.657.751 1.21 0 1.902-.394 2.344-.938.475-.584.742-1.44.878-2.497Z"></path><path d="M14.5 14.25a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0v-2a1 1 0 0 1 1-1Zm-5 0a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0v-2a1 1 0 0 1 1-1Z"></path> </svg> <div> <div class="color-fg-default h4">Copilot for business</div> Enterprise-grade AI features </div> </a></li> <li> <a class="HeaderMenu-dropdown-link d-block no-underline position-relative py-2 Link--secondary d-flex flex-items-center Link--has-description" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;premium_support&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;premium_support_link_enterprise_navbar&quot;}" href="/premium-support"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-comment-discussion color-fg-subtle mr-3"> <path d="M1.75 1h12.5c.966 0 1.75.784 1.75 1.75v9.5A1.75 1.75 0 0 1 14.25 14H8.061l-2.574 2.573A1.458 1.458 0 0 1 3 15.543V14H1.75A1.75 1.75 0 0 1 0 12.25v-9.5C0 1.784.784 1 1.75 1ZM1.5 2.75v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25Z"></path><path d="M22.5 8.75a.25.25 0 0 0-.25-.25h-3.5a.75.75 0 0 1 0-1.5h3.5c.966 0 1.75.784 1.75 1.75v9.5A1.75 1.75 0 0 1 22.25 20H21v1.543a1.457 1.457 0 0 1-2.487 1.03L15.939 20H10.75A1.75 1.75 0 0 1 9 18.25v-1.465a.75.75 0 0 1 1.5 0v1.465c0 .138.112.25.25.25h5.5a.75.75 0 0 1 .53.22l2.72 2.72v-2.19a.75.75 0 0 1 .75-.75h2a.25.25 0 0 0 .25-.25v-9.5Z"></path> </svg> <div> <div class="color-fg-default h4">Premium Support</div> Enterprise-grade 24/7 support </div> </a></li> </ul> </div> </div> </div> </li> <li class="HeaderMenu-item position-relative flex-wrap flex-justify-between flex-items-center d-block d-lg-flex flex-lg-nowrap flex-lg-items-center js-details-container js-header-menu-item"> <a class="HeaderMenu-link no-underline px-0 px-lg-2 py-3 py-lg-2 d-block d-lg-inline-block" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;pricing&quot;,&quot;context&quot;:&quot;global&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;pricing_link_global_navbar&quot;}" href="https://github.com/pricing">Pricing</a> </li> </ul> </nav> <div class="d-flex flex-column flex-lg-row width-full flex-justify-end flex-lg-items-center text-center mt-3 mt-lg-0 text-lg-left ml-lg-3"> <qbsearch-input class="search-input" data-scope="repo:ladjs/lad" data-custom-scopes-path="/search/custom_scopes" data-delete-custom-scopes-csrf="P5w66bUmIMdSQDQpSPmT296xs6v1QWn5A8xnkXUDdLndEMhvblyGu8HHJs5cRek14sKcjz7oXwxfrQWjqlCJYg" data-max-custom-scopes="10" data-header-redesign-enabled="false" data-initial-value="" data-blackbird-suggestions-path="/search/suggestions" data-jump-to-suggestions-path="/_graphql/GetSuggestedNavigationDestinations" data-current-repository="ladjs/lad" data-current-org="ladjs" data-current-owner="" data-logged-in="false" data-copilot-chat-enabled="false" data-nl-search-enabled="false" data-retain-scroll-position="true"> <div class="search-input-container search-with-dialog position-relative d-flex flex-row flex-items-center mr-4 rounded" data-action="click:qbsearch-input#searchInputContainerClicked" > <button type="button" class="header-search-button placeholder input-button form-control d-flex flex-1 flex-self-stretch flex-items-center no-wrap width-full py-0 pl-2 pr-0 text-left border-0 box-shadow-none" data-target="qbsearch-input.inputButton" aria-label="Search or jump to…" aria-haspopup="dialog" placeholder="Search or jump to..." data-hotkey=s,/ autocapitalize="off" data-analytics-event="{&quot;location&quot;:&quot;navbar&quot;,&quot;action&quot;:&quot;searchbar&quot;,&quot;context&quot;:&quot;global&quot;,&quot;tag&quot;:&quot;input&quot;,&quot;label&quot;:&quot;searchbar_input_global_navbar&quot;}" data-action="click:qbsearch-input#handleExpand" > <div class="mr-2 color-fg-muted"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-search"> <path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path> </svg> </div> <span class="flex-1" data-target="qbsearch-input.inputButtonText">Search or jump to...</span> <div class="d-flex" data-target="qbsearch-input.hotkeyIndicator"> <svg xmlns="http://www.w3.org/2000/svg" width="22" height="20" aria-hidden="true" class="mr-1"><path fill="none" stroke="#979A9C" opacity=".4" d="M3.5.5h12c1.7 0 3 1.3 3 3v13c0 1.7-1.3 3-3 3h-12c-1.7 0-3-1.3-3-3v-13c0-1.7 1.3-3 3-3z"></path><path fill="#979A9C" d="M11.8 6L8 15.1h-.9L10.8 6h1z"></path></svg> </div> </button> <input type="hidden" name="type" class="js-site-search-type-field"> <div class="Overlay--hidden " data-modal-dialog-overlay> <modal-dialog data-action="close:qbsearch-input#handleClose cancel:qbsearch-input#handleClose" data-target="qbsearch-input.searchSuggestionsDialog" role="dialog" id="search-suggestions-dialog" aria-modal="true" aria-labelledby="search-suggestions-dialog-header" data-view-component="true" class="Overlay Overlay--width-large Overlay--height-auto"> <h1 id="search-suggestions-dialog-header" class="sr-only">Search code, repositories, users, issues, pull requests...</h1> <div class="Overlay-body Overlay-body--paddingNone"> <div data-view-component="true"> <div class="search-suggestions position-fixed width-full color-shadow-large border color-fg-default color-bg-default overflow-hidden d-flex flex-column query-builder-container" style="border-radius: 12px;" data-target="qbsearch-input.queryBuilderContainer" hidden > <!-- '"` --><!-- </textarea></xmp> --></option></form><form id="query-builder-test-form" action="" accept-charset="UTF-8" method="get"> <query-builder data-target="qbsearch-input.queryBuilder" id="query-builder-query-builder-test" data-filter-key=":" data-view-component="true" class="QueryBuilder search-query-builder"> <div class="FormControl FormControl--fullWidth"> <label id="query-builder-test-label" for="query-builder-test" class="FormControl-label sr-only"> Search </label> <div class="QueryBuilder-StyledInput width-fit " data-target="query-builder.styledInput" > <span id="query-builder-test-leadingvisual-wrap" class="FormControl-input-leadingVisualWrap QueryBuilder-leadingVisualWrap"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-search FormControl-input-leadingVisual"> <path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path> </svg> </span> <div data-target="query-builder.styledInputContainer" class="QueryBuilder-StyledInputContainer"> <div aria-hidden="true" class="QueryBuilder-StyledInputContent" data-target="query-builder.styledInputContent" ></div> <div class="QueryBuilder-InputWrapper"> <div aria-hidden="true" class="QueryBuilder-Sizer" data-target="query-builder.sizer"></div> <input id="query-builder-test" name="query-builder-test" value="" autocomplete="off" type="text" role="combobox" spellcheck="false" aria-expanded="false" aria-describedby="validation-1468f2ed-aa37-470b-a504-e91a2fe9520f" data-target="query-builder.input" data-action=" input:query-builder#inputChange blur:query-builder#inputBlur keydown:query-builder#inputKeydown focus:query-builder#inputFocus " data-view-component="true" class="FormControl-input QueryBuilder-Input FormControl-medium" /> </div> </div> <span class="sr-only" id="query-builder-test-clear">Clear</span> <button role="button" id="query-builder-test-clear-button" aria-labelledby="query-builder-test-clear query-builder-test-label" data-target="query-builder.clearButton" data-action=" click:query-builder#clear focus:query-builder#clearButtonFocus blur:query-builder#clearButtonBlur " variant="small" hidden="hidden" type="button" data-view-component="true" class="Button Button--iconOnly Button--invisible Button--medium mr-1 px-2 py-0 d-flex flex-items-center rounded-1 color-fg-muted"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x-circle-fill Button-visual"> <path d="M2.343 13.657A8 8 0 1 1 13.658 2.343 8 8 0 0 1 2.343 13.657ZM6.03 4.97a.751.751 0 0 0-1.042.018.751.751 0 0 0-.018 1.042L6.94 8 4.97 9.97a.749.749 0 0 0 .326 1.275.749.749 0 0 0 .734-.215L8 9.06l1.97 1.97a.749.749 0 0 0 1.275-.326.749.749 0 0 0-.215-.734L9.06 8l1.97-1.97a.749.749 0 0 0-.326-1.275.749.749 0 0 0-.734.215L8 6.94Z"></path> </svg> </button> </div> <template id="search-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-search"> <path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path> </svg> </template> <template id="code-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code"> <path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path> </svg> </template> <template id="file-code-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-file-code"> <path d="M4 1.75C4 .784 4.784 0 5.75 0h5.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v8.586A1.75 1.75 0 0 1 14.25 15h-9a.75.75 0 0 1 0-1.5h9a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 10 4.25V1.5H5.75a.25.25 0 0 0-.25.25v2.5a.75.75 0 0 1-1.5 0Zm1.72 4.97a.75.75 0 0 1 1.06 0l2 2a.75.75 0 0 1 0 1.06l-2 2a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734l1.47-1.47-1.47-1.47a.75.75 0 0 1 0-1.06ZM3.28 7.78 1.81 9.25l1.47 1.47a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018l-2-2a.75.75 0 0 1 0-1.06l2-2a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Zm8.22-6.218V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path> </svg> </template> <template id="history-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-history"> <path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path> </svg> </template> <template id="repo-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-repo"> <path d="M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25h3.5a.25.25 0 0 1 .25.25v3.25a.25.25 0 0 1-.4.2l-1.45-1.087a.249.249 0 0 0-.3 0L5.4 15.7a.25.25 0 0 1-.4-.2Z"></path> </svg> </template> <template id="bookmark-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-bookmark"> <path d="M3 2.75C3 1.784 3.784 1 4.75 1h6.5c.966 0 1.75.784 1.75 1.75v11.5a.75.75 0 0 1-1.227.579L8 11.722l-3.773 3.107A.751.751 0 0 1 3 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.91l3.023-2.489a.75.75 0 0 1 .954 0l3.023 2.49V2.75a.25.25 0 0 0-.25-.25Z"></path> </svg> </template> <template id="plus-circle-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-plus-circle"> <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7.25-3.25v2.5h2.5a.75.75 0 0 1 0 1.5h-2.5v2.5a.75.75 0 0 1-1.5 0v-2.5h-2.5a.75.75 0 0 1 0-1.5h2.5v-2.5a.75.75 0 0 1 1.5 0Z"></path> </svg> </template> <template id="circle-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-dot-fill"> <path d="M8 4a4 4 0 1 1 0 8 4 4 0 0 1 0-8Z"></path> </svg> </template> <template id="trash-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-trash"> <path d="M11 1.75V3h2.25a.75.75 0 0 1 0 1.5H2.75a.75.75 0 0 1 0-1.5H5V1.75C5 .784 5.784 0 6.75 0h2.5C10.216 0 11 .784 11 1.75ZM4.496 6.675l.66 6.6a.25.25 0 0 0 .249.225h5.19a.25.25 0 0 0 .249-.225l.66-6.6a.75.75 0 0 1 1.492.149l-.66 6.6A1.748 1.748 0 0 1 10.595 15h-5.19a1.75 1.75 0 0 1-1.741-1.575l-.66-6.6a.75.75 0 1 1 1.492-.15ZM6.5 1.75V3h3V1.75a.25.25 0 0 0-.25-.25h-2.5a.25.25 0 0 0-.25.25Z"></path> </svg> </template> <template id="team-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-people"> <path d="M2 5.5a3.5 3.5 0 1 1 5.898 2.549 5.508 5.508 0 0 1 3.034 4.084.75.75 0 1 1-1.482.235 4 4 0 0 0-7.9 0 .75.75 0 0 1-1.482-.236A5.507 5.507 0 0 1 3.102 8.05 3.493 3.493 0 0 1 2 5.5ZM11 4a3.001 3.001 0 0 1 2.22 5.018 5.01 5.01 0 0 1 2.56 3.012.749.749 0 0 1-.885.954.752.752 0 0 1-.549-.514 3.507 3.507 0 0 0-2.522-2.372.75.75 0 0 1-.574-.73v-.352a.75.75 0 0 1 .416-.672A1.5 1.5 0 0 0 11 5.5.75.75 0 0 1 11 4Zm-5.5-.5a2 2 0 1 0-.001 3.999A2 2 0 0 0 5.5 3.5Z"></path> </svg> </template> <template id="project-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-project"> <path d="M1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0ZM1.5 1.75v12.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25ZM11.75 3a.75.75 0 0 1 .75.75v7.5a.75.75 0 0 1-1.5 0v-7.5a.75.75 0 0 1 .75-.75Zm-8.25.75a.75.75 0 0 1 1.5 0v5.5a.75.75 0 0 1-1.5 0ZM8 3a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 3Z"></path> </svg> </template> <template id="pencil-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-pencil"> <path d="M11.013 1.427a1.75 1.75 0 0 1 2.474 0l1.086 1.086a1.75 1.75 0 0 1 0 2.474l-8.61 8.61c-.21.21-.47.364-.756.445l-3.251.93a.75.75 0 0 1-.927-.928l.929-3.25c.081-.286.235-.547.445-.758l8.61-8.61Zm.176 4.823L9.75 4.81l-6.286 6.287a.253.253 0 0 0-.064.108l-.558 1.953 1.953-.558a.253.253 0 0 0 .108-.064Zm1.238-3.763a.25.25 0 0 0-.354 0L10.811 3.75l1.439 1.44 1.263-1.263a.25.25 0 0 0 0-.354Z"></path> </svg> </template> <template id="copilot-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copilot"> <path d="M7.998 15.035c-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.201-.508-.254-1.084-.254-1.656 0-.87.128-1.769.693-2.484.579-.733 1.494-1.124 2.724-1.261 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095v1.872c0 .766-3.351 3.795-8.002 3.795Zm0-1.485c2.28 0 4.584-1.11 5.002-1.433V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-1.146 0-2.059-.327-2.71-.991A3.222 3.222 0 0 1 8 6.303a3.24 3.24 0 0 1-.544.743c-.65.664-1.563.991-2.71.991-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433ZM6.762 2.83c-.193-.206-.637-.413-1.682-.297-1.019.113-1.479.404-1.713.7-.247.312-.369.789-.369 1.554 0 .793.129 1.171.308 1.371.162.181.519.379 1.442.379.853 0 1.339-.235 1.638-.54.315-.322.527-.827.617-1.553.117-.935-.037-1.395-.241-1.614Zm4.155-.297c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Z"></path><path d="M6.25 9.037a.75.75 0 0 1 .75.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 .75-.75Zm4.25.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 1.5 0Z"></path> </svg> </template> <template id="copilot-error-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copilot-error"> <path d="M16 11.24c0 .112-.072.274-.21.467L13 9.688V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-.198 0-.388-.009-.571-.029L6.833 5.226a4.01 4.01 0 0 0 .17-.782c.117-.935-.037-1.395-.241-1.614-.193-.206-.637-.413-1.682-.297-.683.076-1.115.231-1.395.415l-1.257-.91c.579-.564 1.413-.877 2.485-.996 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095Zm-5.083-8.707c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Zm2.511 11.074c-1.393.776-3.272 1.428-5.43 1.428-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.18-.455-.241-.963-.252-1.475L.31 4.107A.747.747 0 0 1 0 3.509V3.49a.748.748 0 0 1 .625-.73c.156-.026.306.047.435.139l14.667 10.578a.592.592 0 0 1 .227.264.752.752 0 0 1 .046.249v.022a.75.75 0 0 1-1.19.596Zm-1.367-.991L5.635 7.964a5.128 5.128 0 0 1-.889.073c-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433 1.539 0 3.089-.505 4.063-.934Z"></path> </svg> </template> <template id="workflow-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-workflow"> <path d="M0 1.75C0 .784.784 0 1.75 0h3.5C6.216 0 7 .784 7 1.75v3.5A1.75 1.75 0 0 1 5.25 7H4v4a1 1 0 0 0 1 1h4v-1.25C9 9.784 9.784 9 10.75 9h3.5c.966 0 1.75.784 1.75 1.75v3.5A1.75 1.75 0 0 1 14.25 16h-3.5A1.75 1.75 0 0 1 9 14.25v-.75H5A2.5 2.5 0 0 1 2.5 11V7h-.75A1.75 1.75 0 0 1 0 5.25Zm1.75-.25a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Zm9 9a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Z"></path> </svg> </template> <template id="book-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-book"> <path d="M0 1.75A.75.75 0 0 1 .75 1h4.253c1.227 0 2.317.59 3 1.501A3.743 3.743 0 0 1 11.006 1h4.245a.75.75 0 0 1 .75.75v10.5a.75.75 0 0 1-.75.75h-4.507a2.25 2.25 0 0 0-1.591.659l-.622.621a.75.75 0 0 1-1.06 0l-.622-.621A2.25 2.25 0 0 0 5.258 13H.75a.75.75 0 0 1-.75-.75Zm7.251 10.324.004-5.073-.002-2.253A2.25 2.25 0 0 0 5.003 2.5H1.5v9h3.757a3.75 3.75 0 0 1 1.994.574ZM8.755 4.75l-.004 7.322a3.752 3.752 0 0 1 1.992-.572H14.5v-9h-3.495a2.25 2.25 0 0 0-2.25 2.25Z"></path> </svg> </template> <template id="code-review-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code-review"> <path d="M1.75 1h12.5c.966 0 1.75.784 1.75 1.75v8.5A1.75 1.75 0 0 1 14.25 13H8.061l-2.574 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25v-8.5C0 1.784.784 1 1.75 1ZM1.5 2.75v8.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-8.5a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25Zm5.28 1.72a.75.75 0 0 1 0 1.06L5.31 7l1.47 1.47a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018l-2-2a.75.75 0 0 1 0-1.06l2-2a.75.75 0 0 1 1.06 0Zm2.44 0a.75.75 0 0 1 1.06 0l2 2a.75.75 0 0 1 0 1.06l-2 2a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L10.69 7 9.22 5.53a.75.75 0 0 1 0-1.06Z"></path> </svg> </template> <template id="codespaces-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-codespaces"> <path d="M0 11.25c0-.966.784-1.75 1.75-1.75h12.5c.966 0 1.75.784 1.75 1.75v3A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm2-9.5C2 .784 2.784 0 3.75 0h8.5C13.216 0 14 .784 14 1.75v5a1.75 1.75 0 0 1-1.75 1.75h-8.5A1.75 1.75 0 0 1 2 6.75Zm1.75-.25a.25.25 0 0 0-.25.25v5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-5a.25.25 0 0 0-.25-.25Zm-2 9.5a.25.25 0 0 0-.25.25v3c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-3a.25.25 0 0 0-.25-.25Z"></path><path d="M7 12.75a.75.75 0 0 1 .75-.75h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1-.75-.75Zm-4 0a.75.75 0 0 1 .75-.75h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1-.75-.75Z"></path> </svg> </template> <template id="comment-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-comment"> <path d="M1 2.75C1 1.784 1.784 1 2.75 1h10.5c.966 0 1.75.784 1.75 1.75v7.5A1.75 1.75 0 0 1 13.25 12H9.06l-2.573 2.573A1.458 1.458 0 0 1 4 13.543V12H2.75A1.75 1.75 0 0 1 1 10.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h4.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> </svg> </template> <template id="comment-discussion-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-comment-discussion"> <path d="M1.75 1h8.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 10.25 10H7.061l-2.574 2.573A1.458 1.458 0 0 1 2 11.543V10h-.25A1.75 1.75 0 0 1 0 8.25v-5.5C0 1.784.784 1 1.75 1ZM1.5 2.75v5.5c0 .138.112.25.25.25h1a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h3.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25Zm13 2a.25.25 0 0 0-.25-.25h-.5a.75.75 0 0 1 0-1.5h.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 14.25 12H14v1.543a1.458 1.458 0 0 1-2.487 1.03L9.22 12.28a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l2.22 2.22v-2.19a.75.75 0 0 1 .75-.75h1a.25.25 0 0 0 .25-.25Z"></path> </svg> </template> <template id="organization-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-organization"> <path d="M1.75 16A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0h8.5C11.216 0 12 .784 12 1.75v12.5c0 .085-.006.168-.018.25h2.268a.25.25 0 0 0 .25-.25V8.285a.25.25 0 0 0-.111-.208l-1.055-.703a.749.749 0 1 1 .832-1.248l1.055.703c.487.325.779.871.779 1.456v5.965A1.75 1.75 0 0 1 14.25 16h-3.5a.766.766 0 0 1-.197-.026c-.099.017-.2.026-.303.026h-3a.75.75 0 0 1-.75-.75V14h-1v1.25a.75.75 0 0 1-.75.75Zm-.25-1.75c0 .138.112.25.25.25H4v-1.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 .75.75v1.25h2.25a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25ZM3.75 6h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1 0-1.5ZM3 3.75A.75.75 0 0 1 3.75 3h.5a.75.75 0 0 1 0 1.5h-.5A.75.75 0 0 1 3 3.75Zm4 3A.75.75 0 0 1 7.75 6h.5a.75.75 0 0 1 0 1.5h-.5A.75.75 0 0 1 7 6.75ZM7.75 3h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1 0-1.5ZM3 9.75A.75.75 0 0 1 3.75 9h.5a.75.75 0 0 1 0 1.5h-.5A.75.75 0 0 1 3 9.75ZM7.75 9h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1 0-1.5Z"></path> </svg> </template> <template id="rocket-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-rocket"> <path d="M14.064 0h.186C15.216 0 16 .784 16 1.75v.186a8.752 8.752 0 0 1-2.564 6.186l-.458.459c-.314.314-.641.616-.979.904v3.207c0 .608-.315 1.172-.833 1.49l-2.774 1.707a.749.749 0 0 1-1.11-.418l-.954-3.102a1.214 1.214 0 0 1-.145-.125L3.754 9.816a1.218 1.218 0 0 1-.124-.145L.528 8.717a.749.749 0 0 1-.418-1.11l1.71-2.774A1.748 1.748 0 0 1 3.31 4h3.204c.288-.338.59-.665.904-.979l.459-.458A8.749 8.749 0 0 1 14.064 0ZM8.938 3.623h-.002l-.458.458c-.76.76-1.437 1.598-2.02 2.5l-1.5 2.317 2.143 2.143 2.317-1.5c.902-.583 1.74-1.26 2.499-2.02l.459-.458a7.25 7.25 0 0 0 2.123-5.127V1.75a.25.25 0 0 0-.25-.25h-.186a7.249 7.249 0 0 0-5.125 2.123ZM3.56 14.56c-.732.732-2.334 1.045-3.005 1.148a.234.234 0 0 1-.201-.064.234.234 0 0 1-.064-.201c.103-.671.416-2.273 1.15-3.003a1.502 1.502 0 1 1 2.12 2.12Zm6.94-3.935c-.088.06-.177.118-.266.175l-2.35 1.521.548 1.783 1.949-1.2a.25.25 0 0 0 .119-.213ZM3.678 8.116 5.2 5.766c.058-.09.117-.178.176-.266H3.309a.25.25 0 0 0-.213.119l-1.2 1.95ZM12 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path> </svg> </template> <template id="shield-check-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-shield-check"> <path d="m8.533.133 5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667l5.25-1.68a1.748 1.748 0 0 1 1.066 0Zm-.61 1.429.001.001-5.25 1.68a.251.251 0 0 0-.174.237V7c0 1.36.275 2.666 1.057 3.859.784 1.194 2.121 2.342 4.366 3.298a.196.196 0 0 0 .154 0c2.245-.957 3.582-2.103 4.366-3.297C13.225 9.666 13.5 8.358 13.5 7V3.48a.25.25 0 0 0-.174-.238l-5.25-1.68a.25.25 0 0 0-.153 0ZM11.28 6.28l-3.5 3.5a.75.75 0 0 1-1.06 0l-1.5-1.5a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l.97.97 2.97-2.97a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path> </svg> </template> <template id="heart-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-heart"> <path d="m8 14.25.345.666a.75.75 0 0 1-.69 0l-.008-.004-.018-.01a7.152 7.152 0 0 1-.31-.17 22.055 22.055 0 0 1-3.434-2.414C2.045 10.731 0 8.35 0 5.5 0 2.836 2.086 1 4.25 1 5.797 1 7.153 1.802 8 3.02 8.847 1.802 10.203 1 11.75 1 13.914 1 16 2.836 16 5.5c0 2.85-2.045 5.231-3.885 6.818a22.066 22.066 0 0 1-3.744 2.584l-.018.01-.006.003h-.002ZM4.25 2.5c-1.336 0-2.75 1.164-2.75 3 0 2.15 1.58 4.144 3.365 5.682A20.58 20.58 0 0 0 8 13.393a20.58 20.58 0 0 0 3.135-2.211C12.92 9.644 14.5 7.65 14.5 5.5c0-1.836-1.414-3-2.75-3-1.373 0-2.609.986-3.029 2.456a.749.749 0 0 1-1.442 0C6.859 3.486 5.623 2.5 4.25 2.5Z"></path> </svg> </template> <template id="server-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-server"> <path d="M1.75 1h12.5c.966 0 1.75.784 1.75 1.75v4c0 .372-.116.717-.314 1 .198.283.314.628.314 1v4a1.75 1.75 0 0 1-1.75 1.75H1.75A1.75 1.75 0 0 1 0 12.75v-4c0-.358.109-.707.314-1a1.739 1.739 0 0 1-.314-1v-4C0 1.784.784 1 1.75 1ZM1.5 2.75v4c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-4a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25Zm.25 5.75a.25.25 0 0 0-.25.25v4c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-4a.25.25 0 0 0-.25-.25ZM7 4.75A.75.75 0 0 1 7.75 4h4.5a.75.75 0 0 1 0 1.5h-4.5A.75.75 0 0 1 7 4.75ZM7.75 10h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM3 4.75A.75.75 0 0 1 3.75 4h.5a.75.75 0 0 1 0 1.5h-.5A.75.75 0 0 1 3 4.75ZM3.75 10h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1 0-1.5Z"></path> </svg> </template> <template id="globe-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-globe"> <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM5.78 8.75a9.64 9.64 0 0 0 1.363 4.177c.255.426.542.832.857 1.215.245-.296.551-.705.857-1.215A9.64 9.64 0 0 0 10.22 8.75Zm4.44-1.5a9.64 9.64 0 0 0-1.363-4.177c-.307-.51-.612-.919-.857-1.215a9.927 9.927 0 0 0-.857 1.215A9.64 9.64 0 0 0 5.78 7.25Zm-5.944 1.5H1.543a6.507 6.507 0 0 0 4.666 5.5c-.123-.181-.24-.365-.352-.552-.715-1.192-1.437-2.874-1.581-4.948Zm-2.733-1.5h2.733c.144-2.074.866-3.756 1.58-4.948.12-.197.237-.381.353-.552a6.507 6.507 0 0 0-4.666 5.5Zm10.181 1.5c-.144 2.074-.866 3.756-1.58 4.948-.12.197-.237.381-.353.552a6.507 6.507 0 0 0 4.666-5.5Zm2.733-1.5a6.507 6.507 0 0 0-4.666-5.5c.123.181.24.365.353.552.714 1.192 1.436 2.874 1.58 4.948Z"></path> </svg> </template> <template id="issue-opened-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-issue-opened"> <path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path> </svg> </template> <template id="device-mobile-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-device-mobile"> <path d="M3.75 0h8.5C13.216 0 14 .784 14 1.75v12.5A1.75 1.75 0 0 1 12.25 16h-8.5A1.75 1.75 0 0 1 2 14.25V1.75C2 .784 2.784 0 3.75 0ZM3.5 1.75v12.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25ZM8 13a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path> </svg> </template> <template id="package-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-package"> <path d="m8.878.392 5.25 3.045c.54.314.872.89.872 1.514v6.098a1.75 1.75 0 0 1-.872 1.514l-5.25 3.045a1.75 1.75 0 0 1-1.756 0l-5.25-3.045A1.75 1.75 0 0 1 1 11.049V4.951c0-.624.332-1.201.872-1.514L7.122.392a1.75 1.75 0 0 1 1.756 0ZM7.875 1.69l-4.63 2.685L8 7.133l4.755-2.758-4.63-2.685a.248.248 0 0 0-.25 0ZM2.5 5.677v5.372c0 .09.047.171.125.216l4.625 2.683V8.432Zm6.25 8.271 4.625-2.683a.25.25 0 0 0 .125-.216V5.677L8.75 8.432Z"></path> </svg> </template> <template id="credit-card-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-credit-card"> <path d="M10.75 9a.75.75 0 0 0 0 1.5h1.5a.75.75 0 0 0 0-1.5h-1.5Z"></path><path d="M0 3.75C0 2.784.784 2 1.75 2h12.5c.966 0 1.75.784 1.75 1.75v8.5A1.75 1.75 0 0 1 14.25 14H1.75A1.75 1.75 0 0 1 0 12.25ZM14.5 6.5h-13v5.75c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25Zm0-2.75a.25.25 0 0 0-.25-.25H1.75a.25.25 0 0 0-.25.25V5h13Z"></path> </svg> </template> <template id="play-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-play"> <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path> </svg> </template> <template id="gift-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-gift"> <path d="M2 2.75A2.75 2.75 0 0 1 4.75 0c.983 0 1.873.42 2.57 1.232.268.318.497.668.68 1.042.183-.375.411-.725.68-1.044C9.376.42 10.266 0 11.25 0a2.75 2.75 0 0 1 2.45 4h.55c.966 0 1.75.784 1.75 1.75v2c0 .698-.409 1.301-1 1.582v4.918A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V9.332C.409 9.05 0 8.448 0 7.75v-2C0 4.784.784 4 1.75 4h.55c-.192-.375-.3-.8-.3-1.25ZM7.25 9.5H2.5v4.75c0 .138.112.25.25.25h4.5Zm1.5 0v5h4.5a.25.25 0 0 0 .25-.25V9.5Zm0-4V8h5.5a.25.25 0 0 0 .25-.25v-2a.25.25 0 0 0-.25-.25Zm-7 0a.25.25 0 0 0-.25.25v2c0 .138.112.25.25.25h5.5V5.5h-5.5Zm3-4a1.25 1.25 0 0 0 0 2.5h2.309c-.233-.818-.542-1.401-.878-1.793-.43-.502-.915-.707-1.431-.707ZM8.941 4h2.309a1.25 1.25 0 0 0 0-2.5c-.516 0-1 .205-1.43.707-.337.392-.646.975-.879 1.793Z"></path> </svg> </template> <template id="code-square-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code-square"> <path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25Zm7.47 3.97a.75.75 0 0 1 1.06 0l2 2a.75.75 0 0 1 0 1.06l-2 2a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L10.69 8 9.22 6.53a.75.75 0 0 1 0-1.06ZM6.78 6.53 5.31 8l1.47 1.47a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215l-2-2a.75.75 0 0 1 0-1.06l2-2a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path> </svg> </template> <template id="device-desktop-icon"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-device-desktop"> <path d="M14.25 1c.966 0 1.75.784 1.75 1.75v7.5A1.75 1.75 0 0 1 14.25 12h-3.727c.099 1.041.52 1.872 1.292 2.757A.752.752 0 0 1 11.25 16h-6.5a.75.75 0 0 1-.565-1.243c.772-.885 1.192-1.716 1.292-2.757H1.75A1.75 1.75 0 0 1 0 10.25v-7.5C0 1.784.784 1 1.75 1ZM1.75 2.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25ZM9.018 12H6.982a5.72 5.72 0 0 1-.765 2.5h3.566a5.72 5.72 0 0 1-.765-2.5Z"></path> </svg> </template> <div class="position-relative"> <ul role="listbox" class="ActionListWrap QueryBuilder-ListWrap" aria-label="Suggestions" data-action=" combobox-commit:query-builder#comboboxCommit mousedown:query-builder#resultsMousedown " data-target="query-builder.resultsList" data-persist-list=false id="query-builder-test-results" ></ul> </div> <div class="FormControl-inlineValidation" id="validation-1468f2ed-aa37-470b-a504-e91a2fe9520f" hidden="hidden"> <span class="FormControl-inlineValidation--visual"> <svg aria-hidden="true" height="12" viewBox="0 0 12 12" version="1.1" width="12" data-view-component="true" class="octicon octicon-alert-fill"> <path d="M4.855.708c.5-.896 1.79-.896 2.29 0l4.675 8.351a1.312 1.312 0 0 1-1.146 1.954H1.33A1.313 1.313 0 0 1 .183 9.058ZM7 7V3H5v4Zm-1 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z"></path> </svg> </span> <span></span> </div> </div> <div data-target="query-builder.screenReaderFeedback" aria-live="polite" aria-atomic="true" class="sr-only"></div> </query-builder></form> <div class="d-flex flex-row color-fg-muted px-3 text-small color-bg-default search-feedback-prompt"> <a target="_blank" href="https://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax" data-view-component="true" class="Link color-fg-accent text-normal ml-2">Search syntax tips</a> <div class="d-flex flex-1"></div> </div> </div> </div> </div> </modal-dialog></div> </div> <div data-action="click:qbsearch-input#retract" class="dark-backdrop position-fixed" hidden data-target="qbsearch-input.darkBackdrop"></div> <div class="color-fg-default"> <dialog-helper> <dialog data-target="qbsearch-input.feedbackDialog" data-action="close:qbsearch-input#handleDialogClose cancel:qbsearch-input#handleDialogClose" id="feedback-dialog" aria-modal="true" aria-labelledby="feedback-dialog-title" aria-describedby="feedback-dialog-description" data-view-component="true" class="Overlay Overlay-whenNarrow Overlay--size-medium Overlay--motion-scaleFade Overlay--disableScroll"> <div data-view-component="true" class="Overlay-header"> <div class="Overlay-headerContentWrap"> <div class="Overlay-titleWrap"> <h1 class="Overlay-title " id="feedback-dialog-title"> Provide feedback </h1> </div> <div class="Overlay-actionWrap"> <button data-close-dialog-id="feedback-dialog" aria-label="Close" type="button" data-view-component="true" class="close-button Overlay-closeButton"><svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x"> <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> </svg></button> </div> </div> </div> <scrollable-region data-labelled-by="feedback-dialog-title"> <div data-view-component="true" class="Overlay-body"> <!-- '"` --><!-- </textarea></xmp> --></option></form><form id="code-search-feedback-form" data-turbo="false" action="/search/feedback" accept-charset="UTF-8" method="post"><input type="hidden" data-csrf="true" name="authenticity_token" value="oW6y/tCdpp2EmwRww6FanmngDVBBowgxdfzhPlpBTSe+D34lKYePsoYrmSxLUBN1v3Nt4y6qW18EsTNUJF8y4g==" /> <p>We read every piece of feedback, and take your input very seriously.</p> <textarea name="feedback" class="form-control width-full mb-2" style="height: 120px" id="feedback"></textarea> <input name="include_email" id="include_email" aria-label="Include my email address so I can be contacted" class="form-control mr-2" type="checkbox"> <label for="include_email" style="font-weight: normal">Include my email address so I can be contacted</label> </form></div> </scrollable-region> <div data-view-component="true" class="Overlay-footer Overlay-footer--alignEnd"> <button data-close-dialog-id="feedback-dialog" type="button" data-view-component="true" class="btn"> Cancel </button> <button form="code-search-feedback-form" data-action="click:qbsearch-input#submitFeedback" type="submit" data-view-component="true" class="btn-primary btn"> Submit feedback </button> </div> </dialog></dialog-helper> <custom-scopes data-target="qbsearch-input.customScopesManager"> <dialog-helper> <dialog data-target="custom-scopes.customScopesModalDialog" data-action="close:qbsearch-input#handleDialogClose cancel:qbsearch-input#handleDialogClose" id="custom-scopes-dialog" aria-modal="true" aria-labelledby="custom-scopes-dialog-title" aria-describedby="custom-scopes-dialog-description" data-view-component="true" class="Overlay Overlay-whenNarrow Overlay--size-medium Overlay--motion-scaleFade Overlay--disableScroll"> <div data-view-component="true" class="Overlay-header Overlay-header--divided"> <div class="Overlay-headerContentWrap"> <div class="Overlay-titleWrap"> <h1 class="Overlay-title " id="custom-scopes-dialog-title"> Saved searches </h1> <h2 id="custom-scopes-dialog-description" class="Overlay-description">Use saved searches to filter your results more quickly</h2> </div> <div class="Overlay-actionWrap"> <button data-close-dialog-id="custom-scopes-dialog" aria-label="Close" type="button" data-view-component="true" class="close-button Overlay-closeButton"><svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x"> <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> </svg></button> </div> </div> </div> <scrollable-region data-labelled-by="custom-scopes-dialog-title"> <div data-view-component="true" class="Overlay-body"> <div data-target="custom-scopes.customScopesModalDialogFlash"></div> <div hidden class="create-custom-scope-form" data-target="custom-scopes.createCustomScopeForm"> <!-- '"` --><!-- </textarea></xmp> --></option></form><form id="custom-scopes-dialog-form" data-turbo="false" action="/search/custom_scopes" accept-charset="UTF-8" method="post"><input type="hidden" data-csrf="true" name="authenticity_token" value="SFrXVS/hVQCr+1twfurHxYPIWH9ObMtj8kQ85vbRtcAYsWQtYgL0rrcKUOkqV4cYlQ6hWJplB3lGGD514cBfXw==" /> <div data-target="custom-scopes.customScopesModalDialogFlash"></div> <input type="hidden" id="custom_scope_id" name="custom_scope_id" data-target="custom-scopes.customScopesIdField"> <div class="form-group"> <label for="custom_scope_name">Name</label> <auto-check src="/search/custom_scopes/check_name" required only-validate-on-blur="false"> <input type="text" name="custom_scope_name" id="custom_scope_name" data-target="custom-scopes.customScopesNameField" class="form-control" autocomplete="off" placeholder="github-ruby" required maxlength="50"> <input type="hidden" data-csrf="true" value="JPWqJher3V77QQhtxAaZ1yGleDMJ8R2Vu8L2bN3YtfYxypujt0l1iLtiXSU7e7nxPADEgZbID75Shr9Z+e+LiA==" /> </auto-check> </div> <div class="form-group"> <label for="custom_scope_query">Query</label> <input type="text" name="custom_scope_query" id="custom_scope_query" data-target="custom-scopes.customScopesQueryField" class="form-control" autocomplete="off" placeholder="(repo:mona/a OR repo:mona/b) AND lang:python" required maxlength="500"> </div> <p class="text-small color-fg-muted"> To see all available qualifiers, see our <a class="Link--inTextBlock" href="https://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax">documentation</a>. </p> </form> </div> <div data-target="custom-scopes.manageCustomScopesForm"> <div data-target="custom-scopes.list"></div> </div> </div> </scrollable-region> <div data-view-component="true" class="Overlay-footer Overlay-footer--alignEnd Overlay-footer--divided"> <button data-action="click:custom-scopes#customScopesCancel" type="button" data-view-component="true" class="btn"> Cancel </button> <button form="custom-scopes-dialog-form" data-action="click:custom-scopes#customScopesSubmit" data-target="custom-scopes.customScopesSubmitButton" type="submit" data-view-component="true" class="btn-primary btn"> Create saved search </button> </div> </dialog></dialog-helper> </custom-scopes> </div> </qbsearch-input> <div class="position-relative HeaderMenu-link-wrap d-lg-inline-block"> <a href="/login?return_to=https%3A%2F%2Fgithub.com%2Fladjs%2Flad%2Ftree%2Fsnyk-fix-bed97d0c625fc25446b4c14528f312d1" class="HeaderMenu-link HeaderMenu-link--sign-in HeaderMenu-button flex-shrink-0 no-underline d-none d-lg-inline-flex border border-lg-0 rounded rounded-lg-0 px-2 py-1" style="margin-left: 12px;" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="e408f48c644ef4427d1b27f1859d43c18428f63e1c5ff1e4b406da79e135a1db" data-analytics-event="{&quot;category&quot;:&quot;Marketing nav&quot;,&quot;action&quot;:&quot;click to go to homepage&quot;,&quot;label&quot;:&quot;ref_page:Marketing;ref_cta:Sign in;ref_loc:Header&quot;}" > Sign in </a> </div> <a href="/signup?ref_cta=Sign+up&amp;ref_loc=header+logged+out&amp;ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Ffiles%2Fdisambiguate&amp;source=header-repo&amp;source_repo=ladjs%2Flad" class="HeaderMenu-link HeaderMenu-link--sign-up HeaderMenu-button flex-shrink-0 d-flex d-lg-inline-flex no-underline border color-border-default rounded px-2 py-1" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="e408f48c644ef4427d1b27f1859d43c18428f63e1c5ff1e4b406da79e135a1db" data-analytics-event="{&quot;category&quot;:&quot;Sign up&quot;,&quot;action&quot;:&quot;click to sign up for account&quot;,&quot;label&quot;:&quot;ref_page:/&lt;user-name&gt;/&lt;repo-name&gt;/files/disambiguate;ref_cta:Sign up;ref_loc:header logged out&quot;}" > Sign up </a> <button type="button" class="sr-only js-header-menu-focus-trap d-block d-lg-none">Reseting focus</button> </div> </div> </div> </div> </header> <div hidden="hidden" data-view-component="true" class="js-stale-session-flash stale-session-flash flash flash-warn flash-full"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert"> <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path> </svg> <span class="js-stale-session-flash-signed-in" hidden>You signed in with another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span> <span class="js-stale-session-flash-signed-out" hidden>You signed out in another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span> <span class="js-stale-session-flash-switched" hidden>You switched accounts on another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span> <button id="icon-button-e9ff83c0-8edb-4ffe-a5c0-b5ca1212377f" aria-labelledby="tooltip-e54bd61e-8d82-4e14-baea-071b3cdd3e77" type="button" data-view-component="true" class="Button Button--iconOnly Button--invisible Button--medium flash-close js-flash-close"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x Button-visual"> <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> </svg> </button><tool-tip id="tooltip-e54bd61e-8d82-4e14-baea-071b3cdd3e77" for="icon-button-e9ff83c0-8edb-4ffe-a5c0-b5ca1212377f" popover="manual" data-direction="s" data-type="label" data-view-component="true" class="sr-only position-absolute">Dismiss alert</tool-tip> </div> </div> <div id="start-of-content" class="show-on-focus"></div> <div id="js-flash-container" class="flash-container" data-turbo-replace> <template class="js-flash-template"> <div class="flash flash-full {{ className }}"> <div > <button autofocus class="flash-close js-flash-close" type="button" aria-label="Dismiss this message"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x"> <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> </svg> </button> <div aria-atomic="true" role="alert" class="js-flash-alert"> <div>{{ message }}</div> </div> </div> </div> </template> </div> <div class="application-main " data-commit-hovercards-enabled data-discussion-hovercards-enabled data-issue-and-pr-hovercards-enabled data-project-hovercards-enabled > <div itemscope itemtype="http://schema.org/SoftwareSourceCode" class=""> <main id="js-repo-pjax-container" > <div id="repository-container-header" class="pt-3 hide-full-screen" style="background-color: var(--page-header-bgColor, var(--color-page-header-bg));" data-turbo-replace> <div class="d-flex flex-nowrap flex-justify-end mb-3 px-3 px-lg-5" style="gap: 1rem;"> <div class="flex-auto min-width-0 width-fit"> <div class=" d-flex flex-wrap flex-items-center wb-break-word f3 text-normal"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-repo color-fg-muted mr-2"> <path d="M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25h3.5a.25.25 0 0 1 .25.25v3.25a.25.25 0 0 1-.4.2l-1.45-1.087a.249.249 0 0 0-.3 0L5.4 15.7a.25.25 0 0 1-.4-.2Z"></path> </svg> <span class="author flex-self-stretch" itemprop="author"> <a class="url fn" rel="author" data-hovercard-type="organization" data-hovercard-url="/orgs/ladjs/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="/ladjs"> ladjs </a> </span> <span class="mx-1 flex-self-stretch color-fg-muted">/</span> <strong itemprop="name" class="mr-2 flex-self-stretch"> <a data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" href="/ladjs/lad">lad</a> </strong> <span></span><span class="Label Label--secondary v-align-middle mr-1">Public</span> </div> </div> <div id="repository-details-container" class="flex-shrink-0" data-turbo-replace style="max-width: 70%;"> <ul class="pagehead-actions flex-shrink-0 d-none d-md-inline" style="padding: 2px 0;"> <li> <include-fragment src="/ladjs/lad/sponsor_button"></include-fragment> </li> <li> <a href="/login?return_to=%2Fladjs%2Flad" rel="nofollow" id="repository-details-watch-button" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;notification subscription menu watch&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;LOG_IN&quot;,&quot;originating_url&quot;:&quot;https://github.com/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="755e1f6d14f9b7827b087753a5acee7212eab401c2cdaa3fabbce5865da01006" aria-label="You must be signed in to change notification settings" data-view-component="true" class="btn-sm btn"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-bell mr-2"> <path d="M8 16a2 2 0 0 0 1.985-1.75c.017-.137-.097-.25-.235-.25h-3.5c-.138 0-.252.113-.235.25A2 2 0 0 0 8 16ZM3 5a5 5 0 0 1 10 0v2.947c0 .05.015.098.042.139l1.703 2.555A1.519 1.519 0 0 1 13.482 13H2.518a1.516 1.516 0 0 1-1.263-2.36l1.703-2.554A.255.255 0 0 0 3 7.947Zm5-3.5A3.5 3.5 0 0 0 4.5 5v2.947c0 .346-.102.683-.294.97l-1.703 2.556a.017.017 0 0 0-.003.01l.001.006c0 .002.002.004.004.006l.006.004.007.001h10.964l.007-.001.006-.004.004-.006.001-.007a.017.017 0 0 0-.003-.01l-1.703-2.554a1.745 1.745 0 0 1-.294-.97V5A3.5 3.5 0 0 0 8 1.5Z"></path> </svg>Notifications </a> <tool-tip id="tooltip-a00d214d-fd5c-4f7c-9447-3bc3f3751402" for="repository-details-watch-button" popover="manual" data-direction="s" data-type="description" data-view-component="true" class="sr-only position-absolute">You must be signed in to change notification settings</tool-tip> </li> <li> <a icon="repo-forked" id="fork-button" href="/login?return_to=%2Fladjs%2Flad" rel="nofollow" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;repo details fork button&quot;,&quot;repository_id&quot;:2791470,&quot;auth_type&quot;:&quot;LOG_IN&quot;,&quot;originating_url&quot;:&quot;https://github.com/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="a43d7a0fd2bc6ea6a73c9a7d62dbea998cd495f5dad7e8766056729b0e6f2ed6" data-view-component="true" class="btn-sm btn"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-repo-forked mr-2"> <path d="M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 1 1.5 0v.878a2.25 2.25 0 0 1-2.25 2.25h-1.5v2.128a2.251 2.251 0 1 1-1.5 0V8.5h-1.5A2.25 2.25 0 0 1 3.5 6.25v-.878a2.25 2.25 0 1 1 1.5 0ZM5 3.25a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Zm6.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm-3 8.75a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Z"></path> </svg>Fork <span id="repo-network-counter" data-pjax-replace="true" data-turbo-replace="true" title="154" data-view-component="true" class="Counter">154</span> </a> </li> <li> <div data-view-component="true" class="BtnGroup d-flex"> <a href="/login?return_to=%2Fladjs%2Flad" rel="nofollow" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;star button&quot;,&quot;repository_id&quot;:2791470,&quot;auth_type&quot;:&quot;LOG_IN&quot;,&quot;originating_url&quot;:&quot;https://github.com/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="8c6ab5001e69ba1da34338c2c4594dbafbf83745f214e956cde7e66e77bbbd19" aria-label="You must be signed in to star a repository" data-view-component="true" class="tooltipped tooltipped-sw btn-sm btn"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-star v-align-text-bottom d-inline-block mr-2"> <path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Zm0 2.445L6.615 5.5a.75.75 0 0 1-.564.41l-3.097.45 2.24 2.184a.75.75 0 0 1 .216.664l-.528 3.084 2.769-1.456a.75.75 0 0 1 .698 0l2.77 1.456-.53-3.084a.75.75 0 0 1 .216-.664l2.24-2.183-3.096-.45a.75.75 0 0 1-.564-.41L8 2.694Z"></path> </svg><span data-view-component="true" class="d-inline"> Star </span> <span id="repo-stars-counter-star" aria-label="2288 users starred this repository" data-singular-suffix="user starred this repository" data-plural-suffix="users starred this repository" data-turbo-replace="true" title="2,288" data-view-component="true" class="Counter js-social-count">2.3k</span> </a></div> </li> </ul> </div> </div> <div id="responsive-meta-container" data-turbo-replace> <div class="d-block d-md-none mb-2 px-3 px-md-4 px-lg-5"> <p class="f4 mb-3 "> Node.js framework made by a former <a class="user-mention" data-hovercard-type="organization" data-hovercard-url="/orgs/expressjs/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/expressjs">@expressjs</a> TC and <a class="user-mention" data-hovercard-type="organization" data-hovercard-url="/orgs/koajs/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/koajs">@koajs</a> team member. Built for <a class="user-mention" data-hovercard-type="organization" data-hovercard-url="/orgs/forwardemail/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/forwardemail">@forwardemail</a>, <a class="user-mention" data-hovercard-type="organization" data-hovercard-url="/orgs/spamscanner/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/spamscanner">@spamscanner</a>, <a class="user-mention" data-hovercard-type="organization" data-hovercard-url="/orgs/breejs/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/breejs">@breejs</a>, <a class="user-mention" data-hovercard-type="organization" data-hovercard-url="/orgs/cabinjs/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/cabinjs">@cabinjs</a>, and <a class="user-mention" data-hovercard-type="organization" data-hovercard-url="/orgs/lassjs/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/lassjs">@lassjs</a>. </p> <div class="mb-2 d-flex flex-items-center Link--secondary"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-link flex-shrink-0 mr-2"> <path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path> </svg> <span class="flex-auto min-width-0 css-truncate css-truncate-target width-fit"> <a title="https://lad.js.org" role="link" target="_blank" class="text-bold" rel="noopener noreferrer" href="https://lad.js.org">lad.js.org</a> </span> </div> <h3 class="sr-only">License</h3> <div class="mb-2"> <a href="/ladjs/lad/blob/master/LICENSE" class="Link--muted" data-analytics-event="{&quot;category&quot;:&quot;Repository Overview&quot;,&quot;action&quot;:&quot;click&quot;,&quot;label&quot;:&quot;location:sidebar;file:license&quot;}" > <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-law mr-2"> <path d="M8.75.75V2h.985c.304 0 .603.08.867.231l1.29.736c.038.022.08.033.124.033h2.234a.75.75 0 0 1 0 1.5h-.427l2.111 4.692a.75.75 0 0 1-.154.838l-.53-.53.529.531-.001.002-.002.002-.006.006-.006.005-.01.01-.045.04c-.21.176-.441.327-.686.45C14.556 10.78 13.88 11 13 11a4.498 4.498 0 0 1-2.023-.454 3.544 3.544 0 0 1-.686-.45l-.045-.04-.016-.015-.006-.006-.004-.004v-.001a.75.75 0 0 1-.154-.838L12.178 4.5h-.162c-.305 0-.604-.079-.868-.231l-1.29-.736a.245.245 0 0 0-.124-.033H8.75V13h2.5a.75.75 0 0 1 0 1.5h-6.5a.75.75 0 0 1 0-1.5h2.5V3.5h-.984a.245.245 0 0 0-.124.033l-1.289.737c-.265.15-.564.23-.869.23h-.162l2.112 4.692a.75.75 0 0 1-.154.838l-.53-.53.529.531-.001.002-.002.002-.006.006-.016.015-.045.04c-.21.176-.441.327-.686.45C4.556 10.78 3.88 11 3 11a4.498 4.498 0 0 1-2.023-.454 3.544 3.544 0 0 1-.686-.45l-.045-.04-.016-.015-.006-.006-.004-.004v-.001a.75.75 0 0 1-.154-.838L2.178 4.5H1.75a.75.75 0 0 1 0-1.5h2.234a.249.249 0 0 0 .125-.033l1.288-.737c.265-.15.564-.23.869-.23h.984V.75a.75.75 0 0 1 1.5 0Zm2.945 8.477c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L13 6.327Zm-10 0c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L3 6.327Z"></path> </svg> MIT license </a> </div> <div class="mb-3"> <a class="Link--secondary no-underline mr-3" href="/ladjs/lad/stargazers"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-star mr-1"> <path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Zm0 2.445L6.615 5.5a.75.75 0 0 1-.564.41l-3.097.45 2.24 2.184a.75.75 0 0 1 .216.664l-.528 3.084 2.769-1.456a.75.75 0 0 1 .698 0l2.77 1.456-.53-3.084a.75.75 0 0 1 .216-.664l2.24-2.183-3.096-.45a.75.75 0 0 1-.564-.41L8 2.694Z"></path> </svg> <span class="text-bold">2.3k</span> stars </a> <a class="Link--secondary no-underline mr-3" href="/ladjs/lad/forks"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-repo-forked mr-1"> <path d="M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 1 1.5 0v.878a2.25 2.25 0 0 1-2.25 2.25h-1.5v2.128a2.251 2.251 0 1 1-1.5 0V8.5h-1.5A2.25 2.25 0 0 1 3.5 6.25v-.878a2.25 2.25 0 1 1 1.5 0ZM5 3.25a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Zm6.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm-3 8.75a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Z"></path> </svg> <span class="text-bold">154</span> forks </a> <a class="Link--secondary no-underline mr-3 d-inline-block" href="/ladjs/lad/branches"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-git-branch mr-1"> <path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path> </svg> <span>Branches</span> </a> <a class="Link--secondary no-underline d-inline-block" href="/ladjs/lad/tags"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-tag mr-1"> <path d="M1 7.775V2.75C1 1.784 1.784 1 2.75 1h5.025c.464 0 .91.184 1.238.513l6.25 6.25a1.75 1.75 0 0 1 0 2.474l-5.026 5.026a1.75 1.75 0 0 1-2.474 0l-6.25-6.25A1.752 1.752 0 0 1 1 7.775Zm1.5 0c0 .066.026.13.073.177l6.25 6.25a.25.25 0 0 0 .354 0l5.025-5.025a.25.25 0 0 0 0-.354l-6.25-6.25a.25.25 0 0 0-.177-.073H2.75a.25.25 0 0 0-.25.25ZM6 5a1 1 0 1 1 0 2 1 1 0 0 1 0-2Z"></path> </svg> <span>Tags</span> </a> <a class="Link--secondary no-underline d-inline-block" href="/ladjs/lad/activity"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-pulse mr-1"> <path d="M6 2c.306 0 .582.187.696.471L10 10.731l1.304-3.26A.751.751 0 0 1 12 7h3.25a.75.75 0 0 1 0 1.5h-2.742l-1.812 4.528a.751.751 0 0 1-1.392 0L6 4.77 4.696 8.03A.75.75 0 0 1 4 8.5H.75a.75.75 0 0 1 0-1.5h2.742l1.812-4.529A.751.751 0 0 1 6 2Z"></path> </svg> <span>Activity</span> </a> </div> <div class="d-flex flex-wrap gap-2"> <div class="flex-1"> <div data-view-component="true" class="BtnGroup d-flex"> <a href="/login?return_to=%2Fladjs%2Flad" rel="nofollow" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;star button&quot;,&quot;repository_id&quot;:2791470,&quot;auth_type&quot;:&quot;LOG_IN&quot;,&quot;originating_url&quot;:&quot;https://github.com/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="8c6ab5001e69ba1da34338c2c4594dbafbf83745f214e956cde7e66e77bbbd19" aria-label="You must be signed in to star a repository" data-view-component="true" class="tooltipped tooltipped-sw btn-sm btn btn-block"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-star v-align-text-bottom d-inline-block mr-2"> <path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Zm0 2.445L6.615 5.5a.75.75 0 0 1-.564.41l-3.097.45 2.24 2.184a.75.75 0 0 1 .216.664l-.528 3.084 2.769-1.456a.75.75 0 0 1 .698 0l2.77 1.456-.53-3.084a.75.75 0 0 1 .216-.664l2.24-2.183-3.096-.45a.75.75 0 0 1-.564-.41L8 2.694Z"></path> </svg><span data-view-component="true" class="d-inline"> Star </span> </a></div> </div> <div class="flex-1"> <a href="/login?return_to=%2Fladjs%2Flad" rel="nofollow" id="files-overview-watch-button" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;notification subscription menu watch&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;LOG_IN&quot;,&quot;originating_url&quot;:&quot;https://github.com/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="755e1f6d14f9b7827b087753a5acee7212eab401c2cdaa3fabbce5865da01006" aria-label="You must be signed in to change notification settings" data-view-component="true" class="btn-sm btn btn-block"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-bell mr-2"> <path d="M8 16a2 2 0 0 0 1.985-1.75c.017-.137-.097-.25-.235-.25h-3.5c-.138 0-.252.113-.235.25A2 2 0 0 0 8 16ZM3 5a5 5 0 0 1 10 0v2.947c0 .05.015.098.042.139l1.703 2.555A1.519 1.519 0 0 1 13.482 13H2.518a1.516 1.516 0 0 1-1.263-2.36l1.703-2.554A.255.255 0 0 0 3 7.947Zm5-3.5A3.5 3.5 0 0 0 4.5 5v2.947c0 .346-.102.683-.294.97l-1.703 2.556a.017.017 0 0 0-.003.01l.001.006c0 .002.002.004.004.006l.006.004.007.001h10.964l.007-.001.006-.004.004-.006.001-.007a.017.017 0 0 0-.003-.01l-1.703-2.554a1.745 1.745 0 0 1-.294-.97V5A3.5 3.5 0 0 0 8 1.5Z"></path> </svg>Notifications </a> <tool-tip id="tooltip-3cc8207b-3025-4379-80b5-c594c609e6f2" for="files-overview-watch-button" popover="manual" data-direction="s" data-type="description" data-view-component="true" class="sr-only position-absolute">You must be signed in to change notification settings</tool-tip> </div> <span> </span> </div> </div> </div> <nav data-pjax="#js-repo-pjax-container" aria-label="Repository" data-view-component="true" class="js-repo-nav js-sidenav-container-pjax js-responsive-underlinenav overflow-hidden UnderlineNav px-3 px-md-4 px-lg-5"> <ul data-view-component="true" class="UnderlineNav-body list-style-none"> <li data-view-component="true" class="d-inline-flex"> <a id="code-tab" href="/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1" data-tab-item="i0code-tab" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches repo_packages repo_deployments repo_attestations /ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g c" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Code&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" aria-current="page" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item selected"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code UnderlineNav-octicon d-none d-sm-inline"> <path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path> </svg> <span data-content="Code">Code</span> <span id="code-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span> </a></li> <li data-view-component="true" class="d-inline-flex"> <a id="issues-tab" href="/ladjs/lad/issues" data-tab-item="i1issues-tab" data-selected-links="repo_issues repo_labels repo_milestones /ladjs/lad/issues" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g i" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Issues&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-issue-opened UnderlineNav-octicon d-none d-sm-inline"> <path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path> </svg> <span data-content="Issues">Issues</span> <span id="issues-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="6" data-view-component="true" class="Counter">6</span> </a></li> <li data-view-component="true" class="d-inline-flex"> <a id="pull-requests-tab" href="/ladjs/lad/pulls" data-tab-item="i2pull-requests-tab" data-selected-links="repo_pulls checks /ladjs/lad/pulls" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g p" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Pull requests&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-git-pull-request UnderlineNav-octicon d-none d-sm-inline"> <path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"></path> </svg> <span data-content="Pull requests">Pull requests</span> <span id="pull-requests-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="45" data-view-component="true" class="Counter">45</span> </a></li> <li data-view-component="true" class="d-inline-flex"> <a id="discussions-tab" href="/ladjs/lad/discussions" data-tab-item="i3discussions-tab" data-selected-links="repo_discussions /ladjs/lad/discussions" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g g" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Discussions&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-comment-discussion UnderlineNav-octicon d-none d-sm-inline"> <path d="M1.75 1h8.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 10.25 10H7.061l-2.574 2.573A1.458 1.458 0 0 1 2 11.543V10h-.25A1.75 1.75 0 0 1 0 8.25v-5.5C0 1.784.784 1 1.75 1ZM1.5 2.75v5.5c0 .138.112.25.25.25h1a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h3.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25Zm13 2a.25.25 0 0 0-.25-.25h-.5a.75.75 0 0 1 0-1.5h.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 14.25 12H14v1.543a1.458 1.458 0 0 1-2.487 1.03L9.22 12.28a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l2.22 2.22v-2.19a.75.75 0 0 1 .75-.75h1a.25.25 0 0 0 .25-.25Z"></path> </svg> <span data-content="Discussions">Discussions</span> <span id="discussions-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span> </a></li> <li data-view-component="true" class="d-inline-flex"> <a id="actions-tab" href="/ladjs/lad/actions" data-tab-item="i4actions-tab" data-selected-links="repo_actions /ladjs/lad/actions" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g a" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Actions&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-play UnderlineNav-octicon d-none d-sm-inline"> <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path> </svg> <span data-content="Actions">Actions</span> <span id="actions-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span> </a></li> <li data-view-component="true" class="d-inline-flex"> <a id="projects-tab" href="/ladjs/lad/projects" data-tab-item="i5projects-tab" data-selected-links="repo_projects new_repo_project repo_project /ladjs/lad/projects" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g b" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Projects&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-table UnderlineNav-octicon d-none d-sm-inline"> <path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25ZM6.5 6.5v8h7.75a.25.25 0 0 0 .25-.25V6.5Zm8-1.5V1.75a.25.25 0 0 0-.25-.25H6.5V5Zm-13 1.5v7.75c0 .138.112.25.25.25H5v-8ZM5 5V1.5H1.75a.25.25 0 0 0-.25.25V5Z"></path> </svg> <span data-content="Projects">Projects</span> <span id="projects-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="0" hidden="hidden" data-view-component="true" class="Counter">0</span> </a></li> <li data-view-component="true" class="d-inline-flex"> <a id="security-tab" href="/ladjs/lad/security" data-tab-item="i6security-tab" data-selected-links="security overview alerts policy token_scanning code_scanning /ladjs/lad/security" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-hotkey="g s" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Security&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-shield UnderlineNav-octicon d-none d-sm-inline"> <path d="M7.467.133a1.748 1.748 0 0 1 1.066 0l5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667Zm.61 1.429a.25.25 0 0 0-.153 0l-5.25 1.68a.25.25 0 0 0-.174.238V7c0 1.358.275 2.666 1.057 3.86.784 1.194 2.121 2.34 4.366 3.297a.196.196 0 0 0 .154 0c2.245-.956 3.582-2.104 4.366-3.298C13.225 9.666 13.5 8.36 13.5 7V3.48a.251.251 0 0 0-.174-.237l-5.25-1.68ZM8.75 4.75v3a.75.75 0 0 1-1.5 0v-3a.75.75 0 0 1 1.5 0ZM9 10.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path> </svg> <span data-content="Security">Security</span> <include-fragment src="/ladjs/lad/security/overall-count" accept="text/fragment+html"></include-fragment> </a></li> <li data-view-component="true" class="d-inline-flex"> <a id="insights-tab" href="/ladjs/lad/pulse" data-tab-item="i7insights-tab" data-selected-links="repo_graphs repo_contributors dependency_graph dependabot_updates pulse people community /ladjs/lad/pulse" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" data-analytics-event="{&quot;category&quot;:&quot;Underline navbar&quot;,&quot;action&quot;:&quot;Click tab&quot;,&quot;label&quot;:&quot;Insights&quot;,&quot;target&quot;:&quot;UNDERLINE_NAV.TAB&quot;}" data-view-component="true" class="UnderlineNav-item no-wrap js-responsive-underlinenav-item js-selected-navigation-item"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-graph UnderlineNav-octicon d-none d-sm-inline"> <path d="M1.5 1.75V13.5h13.75a.75.75 0 0 1 0 1.5H.75a.75.75 0 0 1-.75-.75V1.75a.75.75 0 0 1 1.5 0Zm14.28 2.53-5.25 5.25a.75.75 0 0 1-1.06 0L7 7.06 4.28 9.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.25-3.25a.75.75 0 0 1 1.06 0L10 7.94l4.72-4.72a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path> </svg> <span data-content="Insights">Insights</span> <span id="insights-repo-tab-count" data-pjax-replace="" data-turbo-replace="" title="Not available" data-view-component="true" class="Counter"></span> </a></li> </ul> <div style="visibility:hidden;" data-view-component="true" class="UnderlineNav-actions js-responsive-underlinenav-overflow position-absolute pr-3 pr-md-4 pr-lg-5 right-0"> <action-menu data-select-variant="none" data-view-component="true"> <focus-group direction="vertical" mnemonics retain> <button id="action-menu-69a03304-3661-4a0c-84c4-ae5fb8d650e4-button" popovertarget="action-menu-69a03304-3661-4a0c-84c4-ae5fb8d650e4-overlay" aria-controls="action-menu-69a03304-3661-4a0c-84c4-ae5fb8d650e4-list" aria-haspopup="true" aria-labelledby="tooltip-dd75ceeb-71ce-49ec-97be-4a756464c2cc" type="button" data-view-component="true" class="Button Button--iconOnly Button--secondary Button--medium UnderlineNav-item"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-kebab-horizontal Button-visual"> <path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path> </svg> </button><tool-tip id="tooltip-dd75ceeb-71ce-49ec-97be-4a756464c2cc" for="action-menu-69a03304-3661-4a0c-84c4-ae5fb8d650e4-button" popover="manual" data-direction="s" data-type="label" data-view-component="true" class="sr-only position-absolute">Additional navigation options</tool-tip> <anchored-position data-target="action-menu.overlay" id="action-menu-69a03304-3661-4a0c-84c4-ae5fb8d650e4-overlay" anchor="action-menu-69a03304-3661-4a0c-84c4-ae5fb8d650e4-button" align="start" side="outside-bottom" anchor-offset="normal" popover="auto" data-view-component="true"> <div data-view-component="true" class="Overlay Overlay--size-auto"> <div data-view-component="true" class="Overlay-body Overlay-body--paddingNone"> <action-list> <div data-view-component="true"> <ul aria-labelledby="action-menu-69a03304-3661-4a0c-84c4-ae5fb8d650e4-button" id="action-menu-69a03304-3661-4a0c-84c4-ae5fb8d650e4-list" role="menu" data-view-component="true" class="ActionListWrap--inset ActionListWrap"> <li hidden="hidden" data-menu-item="i0code-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> <a tabindex="-1" id="item-2d2cce3b-7959-434c-8426-0dd7294f5801" href="/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> <span class="ActionListItem-visual ActionListItem-visual--leading"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code"> <path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path> </svg> </span> <span data-view-component="true" class="ActionListItem-label"> Code </span> </a> </li> <li hidden="hidden" data-menu-item="i1issues-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> <a tabindex="-1" id="item-f971b7b5-889c-4ab5-b076-5361178ae988" href="/ladjs/lad/issues" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> <span class="ActionListItem-visual ActionListItem-visual--leading"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-issue-opened"> <path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path> </svg> </span> <span data-view-component="true" class="ActionListItem-label"> Issues </span> </a> </li> <li hidden="hidden" data-menu-item="i2pull-requests-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> <a tabindex="-1" id="item-26341061-69bf-4cfc-95b0-a11caa8c8665" href="/ladjs/lad/pulls" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> <span class="ActionListItem-visual ActionListItem-visual--leading"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-git-pull-request"> <path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"></path> </svg> </span> <span data-view-component="true" class="ActionListItem-label"> Pull requests </span> </a> </li> <li hidden="hidden" data-menu-item="i3discussions-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> <a tabindex="-1" id="item-b7a1afdf-488e-443c-a056-98e7aa1ef977" href="/ladjs/lad/discussions" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> <span class="ActionListItem-visual ActionListItem-visual--leading"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-comment-discussion"> <path d="M1.75 1h8.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 10.25 10H7.061l-2.574 2.573A1.458 1.458 0 0 1 2 11.543V10h-.25A1.75 1.75 0 0 1 0 8.25v-5.5C0 1.784.784 1 1.75 1ZM1.5 2.75v5.5c0 .138.112.25.25.25h1a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h3.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25Zm13 2a.25.25 0 0 0-.25-.25h-.5a.75.75 0 0 1 0-1.5h.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 14.25 12H14v1.543a1.458 1.458 0 0 1-2.487 1.03L9.22 12.28a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l2.22 2.22v-2.19a.75.75 0 0 1 .75-.75h1a.25.25 0 0 0 .25-.25Z"></path> </svg> </span> <span data-view-component="true" class="ActionListItem-label"> Discussions </span> </a> </li> <li hidden="hidden" data-menu-item="i4actions-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> <a tabindex="-1" id="item-26212432-df96-4ae2-a793-80de13ba2624" href="/ladjs/lad/actions" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> <span class="ActionListItem-visual ActionListItem-visual--leading"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-play"> <path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path> </svg> </span> <span data-view-component="true" class="ActionListItem-label"> Actions </span> </a> </li> <li hidden="hidden" data-menu-item="i5projects-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> <a tabindex="-1" id="item-d8830a5f-9941-45b9-9266-30f2ddd5381a" href="/ladjs/lad/projects" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> <span class="ActionListItem-visual ActionListItem-visual--leading"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-table"> <path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25ZM6.5 6.5v8h7.75a.25.25 0 0 0 .25-.25V6.5Zm8-1.5V1.75a.25.25 0 0 0-.25-.25H6.5V5Zm-13 1.5v7.75c0 .138.112.25.25.25H5v-8ZM5 5V1.5H1.75a.25.25 0 0 0-.25.25V5Z"></path> </svg> </span> <span data-view-component="true" class="ActionListItem-label"> Projects </span> </a> </li> <li hidden="hidden" data-menu-item="i6security-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> <a tabindex="-1" id="item-dbde9fba-8e1f-4b3f-96c6-84dbd1bf4bf7" href="/ladjs/lad/security" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> <span class="ActionListItem-visual ActionListItem-visual--leading"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-shield"> <path d="M7.467.133a1.748 1.748 0 0 1 1.066 0l5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667Zm.61 1.429a.25.25 0 0 0-.153 0l-5.25 1.68a.25.25 0 0 0-.174.238V7c0 1.358.275 2.666 1.057 3.86.784 1.194 2.121 2.34 4.366 3.297a.196.196 0 0 0 .154 0c2.245-.956 3.582-2.104 4.366-3.298C13.225 9.666 13.5 8.36 13.5 7V3.48a.251.251 0 0 0-.174-.237l-5.25-1.68ZM8.75 4.75v3a.75.75 0 0 1-1.5 0v-3a.75.75 0 0 1 1.5 0ZM9 10.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path> </svg> </span> <span data-view-component="true" class="ActionListItem-label"> Security </span> </a> </li> <li hidden="hidden" data-menu-item="i7insights-tab" data-targets="action-list.items" role="none" data-view-component="true" class="ActionListItem"> <a tabindex="-1" id="item-0e0bae62-e80a-45be-ad19-585dd32729b9" href="/ladjs/lad/pulse" role="menuitem" data-view-component="true" class="ActionListContent ActionListContent--visual16"> <span class="ActionListItem-visual ActionListItem-visual--leading"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-graph"> <path d="M1.5 1.75V13.5h13.75a.75.75 0 0 1 0 1.5H.75a.75.75 0 0 1-.75-.75V1.75a.75.75 0 0 1 1.5 0Zm14.28 2.53-5.25 5.25a.75.75 0 0 1-1.06 0L7 7.06 4.28 9.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.25-3.25a.75.75 0 0 1 1.06 0L10 7.94l4.72-4.72a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path> </svg> </span> <span data-view-component="true" class="ActionListItem-label"> Insights </span> </a> </li> </ul> </div></action-list> </div> </div></anchored-position> </focus-group> </action-menu></div> </nav> </div> <turbo-frame id="repo-content-turbo-frame" target="_top" data-turbo-action="advance" class=""> <div id="repo-content-pjax-container" class="repository-content " > <h1 class='sr-only'>ladjs/lad</h1> <div class="clearfix container-xl px-md-4 px-lg-5 px-3"> <div> <div style="max-width: 100%" data-view-component="true" class="Layout Layout--flowRow-until-md react-repos-overview-margin Layout--sidebarPosition-end Layout--sidebarPosition-flowRow-end"> <div data-view-component="true" class="Layout-main"> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_dompurify_dist_purify_es_mjs-dd1d3ea6a436.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/vendors-node_modules_tanstack_query-core_build_modern_queryObserver_js-node_modules_tanstack_-defd52-843b41414e0e.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_aria-live_aria-live_ts-ui_packages_promise-with-resolvers-polyfill_promise-with-r-17c672-34345cb18aac.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_paths_index_ts-1b92c4b9d0a5.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_ref-selector_RefSelector_tsx-7496afc3784d.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_commit-attribution_index_ts-ui_packages_commit-checks-status_index_ts-ui_packages-7094d4-15017f02e61c.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/ui_packages_code-view-shared_hooks_use-canonical-object_ts-ui_packages_code-view-shared_hooks-5f1d09-1ee828c2d6e8.js"></script> <script crossorigin="anonymous" defer="defer" type="application/javascript" src="https://github.githubassets.com/assets/repos-overview-d245eae13daf.js"></script> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react.2708311ccb5cb34358b1.module.css" /> <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/repos-overview.0ee7cac3ab511a65d9f9.module.css" /> <react-partial partial-name="repos-overview" data-ssr="true" data-attempted-ssr="true" > <script type="application/json" data-target="react-partial.embeddedData">{"props":{"initialPayload":{"allShortcutsEnabled":false,"path":"/","repo":{"id":2791470,"defaultBranch":"master","name":"lad","ownerLogin":"ladjs","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2011-11-16T22:08:03.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/30959108?v=4","public":true,"private":false,"isOrgOwned":true},"currentUser":null,"refInfo":{"name":"snyk-fix-bed97d0c625fc25446b4c14528f312d1","listCacheKey":"v0:1742626054.0","canEdit":false,"refType":"branch","currentOid":"19298f282139c8d83de0d323e3b68abd02fe31f7"},"tree":{"items":[{"name":".github","path":".github","contentType":"directory"},{"name":"media","path":"media","contentType":"directory"},{"name":"template","path":"template","contentType":"directory"},{"name":"test","path":"test","contentType":"directory"},{"name":".browserslistrc","path":".browserslistrc","contentType":"file"},{"name":".editorconfig","path":".editorconfig","contentType":"file"},{"name":".gitattributes","path":".gitattributes","contentType":"file"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":".lintstagedrc.js","path":".lintstagedrc.js","contentType":"file"},{"name":".nojekyll","path":".nojekyll","contentType":"file"},{"name":".npmignore","path":".npmignore","contentType":"file"},{"name":".npmrc","path":".npmrc","contentType":"file"},{"name":".remarkignore","path":".remarkignore","contentType":"file"},{"name":".travis.yml","path":".travis.yml","contentType":"file"},{"name":"CNAME","path":"CNAME","contentType":"file"},{"name":"LICENSE","path":"LICENSE","contentType":"file"},{"name":"README.md","path":"README.md","contentType":"file"},{"name":"cli.js","path":"cli.js","contentType":"file"},{"name":"config.js","path":"config.js","contentType":"file"},{"name":"favicon.ico","path":"favicon.ico","contentType":"file"},{"name":"index.html","path":"index.html","contentType":"file"},{"name":"package.json","path":"package.json","contentType":"file"},{"name":"sao.js","path":"sao.js","contentType":"file"},{"name":"yarn.lock","path":"yarn.lock","contentType":"file"}],"templateDirectorySuggestionUrl":null,"readme":null,"totalCount":24,"showBranchInfobar":true},"fileTree":null,"fileTreeProcessingTime":null,"foldersToFetch":[],"treeExpanded":false,"symbolsExpanded":false,"isOverview":true,"overview":{"banners":{"shouldRecommendReadme":false,"isPersonalRepo":false,"showUseActionBanner":false,"actionSlug":null,"actionId":null,"showProtectBranchBanner":false,"publishBannersInfo":{"dismissActionNoticePath":"/settings/dismiss-notice/publish_action_from_repo","releasePath":"/ladjs/lad/releases/new?marketplace=true","showPublishActionBanner":false},"interactionLimitBanner":null,"showInvitationBanner":false,"inviterName":null,"actionsMigrationBannerInfo":{"releaseTags":[],"showImmutableActionsMigrationBanner":false,"initialMigrationStatus":null}},"codeButton":{"contactPath":"/contact","isEnterprise":false,"local":{"protocolInfo":{"httpAvailable":true,"sshAvailable":null,"httpUrl":"https://github.com/ladjs/lad.git","showCloneWarning":null,"sshUrl":null,"sshCertificatesRequired":null,"sshCertificatesAvailable":null,"ghCliUrl":"gh repo clone ladjs/lad","defaultProtocol":"http","newSshKeyUrl":"/settings/ssh/new","setProtocolPath":"/users/set_protocol"},"platformInfo":{"cloneUrl":"https://desktop.github.com","showVisualStudioCloneButton":false,"visualStudioCloneUrl":"https://windows.github.com","showXcodeCloneButton":false,"xcodeCloneUrl":"xcode://clone?repo=https%3A%2F%2Fgithub.com%2Fladjs%2Flad","zipballUrl":"/ladjs/lad/archive/refs/heads/snyk-fix-bed97d0c625fc25446b4c14528f312d1.zip"}},"newCodespacePath":"/codespaces/new?hide_repo_select=true\u0026ref=snyk-fix-bed97d0c625fc25446b4c14528f312d1\u0026repo=2791470"},"popovers":{"rename":null,"renamedParentRepo":null},"commitCount":"344","overviewFiles":[{"displayName":"README.md","repoName":"lad","refName":"snyk-fix-bed97d0c625fc25446b4c14528f312d1","path":"README.md","preferredFileType":"readme","tabName":"README","richText":"\u003carticle class=\"markdown-body entry-content container-lg\" itemprop=\"text\"\u003e\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch1 align=\"center\" tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003e\n \u003ca href=\"https://ladjs.github.io/lad/\" rel=\"nofollow\"\u003e\u003cimg src=\"/ladjs/lad/raw/snyk-fix-bed97d0c625fc25446b4c14528f312d1/media/lad.png\" alt=\"lad\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\n\u003c/h1\u003e\u003ca id=\"user-content---\" class=\"anchor\" aria-label=\"Permalink: \" href=\"#--\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv align=\"center\" dir=\"auto\"\u003e\n \u003ca href=\"https://join.slack.com/t/ladjs/shared_invite/zt-fqei6z11-Bq2trhwHQxVc5x~ifiZG0g\" rel=\"nofollow\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/6dd9e714205d1d4bacbf2c6a04fe9fa2a33208a1c6babf547101166d0d5c0e81/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636861742d6a6f696e253230736c61636b2d627269676874677265656e\" alt=\"chat\" data-canonical-src=\"https://img.shields.io/badge/chat-join%20slack-brightgreen\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\n \u003ca href=\"https://travis-ci.org/ladjs/lad\" rel=\"nofollow\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/c08a0dabec4436cf3029dc17c37f395d32eff7f05120f178f3bcf04fd8731f20/68747470733a2f2f7472617669732d63692e6f72672f6c61646a732f6c61642e7376673f6272616e63683d6d6173746572\" alt=\"build status\" data-canonical-src=\"https://travis-ci.org/ladjs/lad.svg?branch=master\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\n \u003ca href=\"https://codecov.io/github/ladjs/lad\" rel=\"nofollow\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/cb18625953f4cfccd27732129da5d4329bab291dd745fc148776c8ade3113c62/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f6c61646a732f6c61642f6d61737465722e737667\" alt=\"code coverage\" data-canonical-src=\"https://img.shields.io/codecov/c/github/ladjs/lad/master.svg\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\n \u003ca href=\"https://github.com/sindresorhus/xo\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/e40c657b8e9f62e24c6806f6221b4deec91873208ff9d78c9acb75baa843b66a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f64655f7374796c652d584f2d3565643963372e737667\" alt=\"code style\" data-canonical-src=\"https://img.shields.io/badge/code_style-XO-5ed9c7.svg\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\n \u003ca href=\"https://github.com/prettier/prettier\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/3bacc065fff241f323175f9ddb92715c4a989b9d8c70321a0c3823e9d7ba8fea/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7374796c65645f776974682d70726574746965722d6666363962342e737667\" alt=\"styled with prettier\" data-canonical-src=\"https://img.shields.io/badge/styled_with-prettier-ff69b4.svg\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\n \u003ca href=\"https://lass.js.org\" rel=\"nofollow\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/fc8ee60db54e388140d708db4d01b2d90522265847e077b22fc4cd09b0fe68f0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6d6164655f776974682d6c6173732d3935434332382e737667\" alt=\"made with lass\" data-canonical-src=\"https://img.shields.io/badge/made_with-lass-95CC28.svg\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\n \u003ca href=\"/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/LICENSE\"\u003e\u003cimg src=\"https://camo.githubusercontent.com/8468249e3d59c31fee6c1c0bffd23df0185ff41bc9888f485f4469bc72073865/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6c61646a732f6c61642e737667\" alt=\"license\" data-canonical-src=\"https://img.shields.io/github/license/ladjs/lad.svg\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\u003cdiv align=\"center\" dir=\"auto\"\u003e\n Lad is the best \u003ca href=\"https://nodejs.org\" rel=\"nofollow\"\u003eNode.js\u003c/a\u003e framework. Made by a former \u003ca href=\"https://github.com/expressjs/express\"\u003eExpress\u003c/a\u003e TC and \u003ca href=\"https://github.com/koajs/koa\"\u003eKoa\u003c/a\u003e team member.\n\u003c/div\u003e\n\u003cdiv align=\"center\" dir=\"auto\"\u003e\n \u003csub\u003e\n A lad that fell in love with a \u003ca href=\"https://lass.js.org\" rel=\"nofollow\"\u003e\u003cstrong\u003elass\u003c/strong\u003e\u003c/a\u003e\n • Built by \u003ca href=\"https://github.com/niftylettuce\"\u003e@niftylettuce\u003c/a\u003e\n and \u003ca href=\"#contributors\"\u003econtributors\u003c/a\u003e\n \u003c/sub\u003e\n\u003c/div\u003e\n\u003chr\u003e\n\u003cdiv align=\"center\" dir=\"auto\"\u003e\n \u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eProject Spotlight: Forward Email @ \u003ca href=\"https://forwardemail.net\" rel=\"nofollow\"\u003ehttps://forwardemail.net\u003c/a\u003e (made with Lad)\u003c/h3\u003e\u003ca id=\"user-content-project-spotlight-forward-email--httpsforwardemailnet-made-with-lad\" class=\"anchor\" aria-label=\"Permalink: Project Spotlight: Forward Email @ https://forwardemail.net (made with Lad)\" href=\"#project-spotlight-forward-email--httpsforwardemailnet-made-with-lad\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n \u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eLive Framework Demo: \u003ca href=\"https://lad.sh\" rel=\"nofollow\"\u003ehttps://lad.sh\u003c/a\u003e\u003c/h4\u003e\u003ca id=\"user-content-live-framework-demo-httpsladsh\" class=\"anchor\" aria-label=\"Permalink: Live Framework Demo:https://lad.sh\" href=\"#live-framework-demo-httpsladsh\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003c/div\u003e\n\u003chr\u003e\n\u003cdiv align=\"center\" dir=\"auto\"\u003e❤️ Love this project? Support \u003ca href=\"https://github.com/niftylettuce\"\u003e@niftylettuce's\u003c/a\u003e \u003ca href=\"https://en.wikipedia.org/wiki/Free_and_open-source_software\" rel=\"nofollow\"\u003eFOSS\u003c/a\u003e on \u003ca href=\"https://patreon.com/niftylettuce\" rel=\"nofollow\"\u003ePatreon\u003c/a\u003e or \u003ca href=\"https://paypal.me/niftylettuce\" rel=\"nofollow\"\u003ePayPal\u003c/a\u003e 🦄\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTable of Contents\u003c/h2\u003e\u003ca id=\"user-content-table-of-contents\" class=\"anchor\" aria-label=\"Permalink: Table of Contents\" href=\"#table-of-contents\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ca href=\"#features\"\u003eFeatures\u003c/a\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ca href=\"#microservices\"\u003eMicroservices\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#front-end\"\u003eFront-end\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#back-end\"\u003eBack-end\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#translation\"\u003eTranslation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#email-engine\"\u003eEmail Engine\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#error-handling\"\u003eError Handling\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#performance\"\u003ePerformance\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#security\"\u003eSecurity\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#get-started\"\u003eGet Started\u003c/a\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ca href=\"#requirements\"\u003eRequirements\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#install\"\u003eInstall\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#usage\"\u003eUsage\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#configuration\"\u003eConfiguration\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#tutorials\"\u003eTutorials\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#community\"\u003eCommunity\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#architecture\"\u003eArchitecture\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#principles\"\u003ePrinciples\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#related\"\u003eRelated\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#contributing\"\u003eContributing\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#contributors\"\u003eContributors\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#trademark-notice\"\u003eTrademark Notice\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#license\"\u003eLicense\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eFeatures\u003c/h2\u003e\u003ca id=\"user-content-features\" class=\"anchor\" aria-label=\"Permalink: Features\" href=\"#features\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eLad boasts dozens of features and is extremely configurable.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eMicroservices\u003c/h3\u003e\u003ca id=\"user-content-microservices\" class=\"anchor\" aria-label=\"Permalink: Microservices\" href=\"#microservices\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThese microservices are preconfigured for security, performance, and graceful reloading.\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eWebapp server → \u003ca href=\"/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/web.js\"\u003eweb.js\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eAPI server → \u003ca href=\"/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/api.js\"\u003eapi.js\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eJob scheduler → \u003ca href=\"/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/bree.js\"\u003ebree.js\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eProxy server → \u003ca href=\"/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/proxy.js\"\u003eproxy.js\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eFront-end\u003c/h3\u003e\u003ca id=\"user-content-front-end\" class=\"anchor\" aria-label=\"Permalink: Front-end\" href=\"#front-end\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eBrowser linting using \u003ca href=\"https://github.com/amilajack/eslint-plugin-compat\"\u003eeslint-plugin-compat\u003c/a\u003e and \u003ca href=\"https://github.com/ai/browserslist\"\u003ebrowserslist\u003c/a\u003e (see \u003ca href=\"/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/.browserslistrc\"\u003e.browserslistrc\u003c/a\u003e for the default config)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://pugjs.org\" rel=\"nofollow\"\u003ePug\u003c/a\u003e template engine (you can easily use \u003ca href=\"https://github.com/kbrsh/moon\"\u003eMoon\u003c/a\u003e, \u003ca href=\"https://vuejs.org/\" rel=\"nofollow\"\u003eVue\u003c/a\u003e, \u003ca href=\"https://facebook.github.io/react/\" rel=\"nofollow\"\u003eReact\u003c/a\u003e, or \u003ca href=\"https://angular.io/\" rel=\"nofollow\"\u003eAngular\u003c/a\u003e, though typically \u003ca href=\"https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it\" rel=\"nofollow\"\u003eyou aren't going to need it\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://gulpjs.com\" rel=\"nofollow\"\u003eGulp\u003c/a\u003e (latest version 4.x)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://sass-lang.com/\" rel=\"nofollow\"\u003eSass\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://postcss.org/\" rel=\"nofollow\"\u003ePostCSS\u003c/a\u003e (with \u003ca href=\"https://github.com/jonathantneal/postcss-font-magician\"\u003efont-magician\u003c/a\u003e, \u003ca href=\"https://github.com/unlight/postcss-import-url\"\u003eimport-url\u003c/a\u003e, \u003ca href=\"https://github.com/AaronJan/postcss-font-grabber\"\u003efont-grabber\u003c/a\u003e, \u003ca href=\"https://github.com/jelmerdemaat/postcss-base64\"\u003ebase64\u003c/a\u003e, and \u003ca href=\"http://cssnext.io/\" rel=\"nofollow\"\u003ecssnext\u003c/a\u003e pre-configured)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://getbootstrap.com/\" rel=\"nofollow\"\u003eBootstrap\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://fontawesome.io/\" rel=\"nofollow\"\u003eFont Awesome\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://tobiasahlin.com/spinkit/\" rel=\"nofollow\"\u003eSpinKit\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://limonte.github.io/sweetalert2/\" rel=\"nofollow\"\u003eSweetAlert2\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://dense.rah.pw/\" rel=\"nofollow\"\u003eDense\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://imakewebthings.com/waypoints/\" rel=\"nofollow\"\u003eWaypoints\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/intesso/connect-livereload\"\u003eLiveReload\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e…\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eBack-end\u003c/h3\u003e\u003ca id=\"user-content-back-end\" class=\"anchor\" aria-label=\"Permalink: Back-end\" href=\"#back-end\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRedis, sessions, and flash toast and modal \u003ca href=\"https://limonte.github.io/sweetalert2/\" rel=\"nofollow\"\u003eSweetAlert2\u003c/a\u003e messages (uses \u003ca href=\"https://github.com/luin/ioredis\"\u003eioredis\u003c/a\u003e which has support for \u003ca href=\"https://redis.io/topics/cluster-tutorial\" rel=\"nofollow\"\u003eCluster\u003c/a\u003e, \u003ca href=\"https://redis.io/topics/sentinel\" rel=\"nofollow\"\u003eSentinel\u003c/a\u003e, and more)\u003c/li\u003e\n\u003cli\u003eKoa-based webapp and API servers (uses HTTP/2 for production!)\u003c/li\u003e\n\u003cli\u003ePagination built-in (using \u003ca href=\"https://github.com/koajs/ctx-paginate\"\u003ectx-paginate\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eRESTful API with BasicAuth and versioning\u003c/li\u003e\n\u003cli\u003eAutomated job scheduler with cron and human-readable syntax (backed by \u003ca href=\"http://mongoosejs.com\" rel=\"nofollow\"\u003eMongoose\u003c/a\u003e and \u003ca href=\"https://jobscheduler.net\" rel=\"nofollow\"\u003eBree\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003ePassport-based authentication and group-based (Unix-like) permissioning\u003c/li\u003e\n\u003cli\u003eStripe-inspired error handling\u003c/li\u003e\n\u003cli\u003eMongoose and MongoDB with common database plugins\u003c/li\u003e\n\u003cli\u003eEmail template engine with \u003ca href=\"https://nodemailer.com/\" rel=\"nofollow\"\u003eNodemailer\u003c/a\u003e and local rendering\u003c/li\u003e\n\u003cli\u003eProxy eliminates need for Nginx reverse-proxy or Apache virtual hosts\u003c/li\u003e\n\u003cli\u003eMultilingual through built-in i18n translation support (\u003ca href=\"#translation-configuration\"\u003esee configuration\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAutomatic phrase translation with Google Translate\u003c/li\u003e\n\u003cli\u003eSitemap generator for simple SEO\u003c/li\u003e\n\u003cli\u003e…\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTranslation\u003c/h3\u003e\u003ca id=\"user-content-translation\" class=\"anchor\" aria-label=\"Permalink: Translation\" href=\"#translation\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eFinally a framework that solves i18n everywhere; complete with automatic translation.\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eTranslation constants built-in so you \u003ca href=\"https://en.wikipedia.org/wiki/Don%27t_repeat_yourself\" rel=\"nofollow\"\u003edon't repeat yourself\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eWebapp error messages and templates are translated\u003c/li\u003e\n\u003cli\u003eEmails are translated\u003c/li\u003e\n\u003cli\u003eAPI responses are translated\u003c/li\u003e\n\u003cli\u003eDatabase errors are translated\u003c/li\u003e\n\u003cli\u003eAuthentication errors are translated\u003c/li\u003e\n\u003cli\u003e…\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eEmail Engine\u003c/h3\u003e\u003ca id=\"user-content-email-engine\" class=\"anchor\" aria-label=\"Permalink: Email Engine\" href=\"#email-engine\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eOur beautiful email engine uses \u003ca href=\"https://github.com/niftylettuce/node-email-templates\"\u003eemail-templates\u003c/a\u003e (which is also made by the creator of Lad)!\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eTest your emails locally with automatic browser-rendering on the fly\u003c/li\u003e\n\u003cli\u003eAutomatically inlines CSS for cross-browser and cross-platform email client support\u003c/li\u003e\n\u003cli\u003eUse \u003ca href=\"https://getbootstrap.com/\" rel=\"nofollow\"\u003eBootstrap\u003c/a\u003e in your email template designs\u003c/li\u003e\n\u003cli\u003eReuse your existing CSS and webapp styling\u003c/li\u003e\n\u003cli\u003eUse any template engine (defaults to Pug)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ladjs/custom-fonts-in-emails\"\u003eRender custom fonts in emails with code\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ladjs/font-awesome-assets\"\u003eAdd icons with Font Awesome with code\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ladjs/nodemailer-base64-to-s3\"\u003eAutomatically avoid email client caching\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eInclude any image you want and it will be properly rendered\u003c/li\u003e\n\u003cli\u003eRids the need for awkward embedded image CID attachments\u003c/li\u003e\n\u003cli\u003e…\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eError Handling\u003c/h3\u003e\u003ca id=\"user-content-error-handling\" class=\"anchor\" aria-label=\"Permalink: Error Handling\" href=\"#error-handling\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWe've spent a lot of time designing a beautiful error handler.\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eSupports \u003ccode\u003etext/html\u003c/code\u003e, \u003ccode\u003eapplication/json\u003c/code\u003e, and \u003ccode\u003etext\u003c/code\u003e response types\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/niftylettuce/koa-better-error-handler#user-friendly-responses\"\u003eUser-friendly responses\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/niftylettuce/koa-better-error-handler#html-error-lists\"\u003eHTML error lists\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e…\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eSee \u003ca href=\"https://github.com/niftylettuce/koa-better-error-handler\"\u003ekoa-better-error-handler\u003c/a\u003e for a complete reference.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePerformance\u003c/h3\u003e\u003ca id=\"user-content-performance\" class=\"anchor\" aria-label=\"Permalink: Performance\" href=\"#performance\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eCompression and zero-bloat approach\u003c/li\u003e\n\u003cli\u003eStream-based file uploading\u003c/li\u003e\n\u003cli\u003eGraceful reloading, shutdown, and reconnection handling\u003c/li\u003e\n\u003cli\u003eManifest asset revisioning\u003c/li\u003e\n\u003cli\u003eAmazon S3 and CloudFront ready\u003c/li\u003e\n\u003cli\u003e…\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSecurity\u003c/h3\u003e\u003ca id=\"user-content-security\" class=\"anchor\" aria-label=\"Permalink: Security\" href=\"#security\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eDatabase security plugins and helpers\u003c/li\u003e\n\u003cli\u003eAutomated tests and code coverage\u003c/li\u003e\n\u003cli\u003eCORS, SameSite set to \"lax\" (\u003ca href=\"https://scotthelme.co.uk/csrf-is-dead/\" rel=\"nofollow\"\u003ean alternative to CSRF\u003c/a\u003e), CSRF (since \u003ca href=\"https://caniuse.com/#search=SameSite\" rel=\"nofollow\"\u003enot all browsers\u003c/a\u003e support SameSite yet) XSS, and rate limited protection\u003c/li\u003e\n\u003cli\u003eDotenv support for environment-based configurations\u003c/li\u003e\n\u003cli\u003eApp, user, and request-based logging\u003c/li\u003e\n\u003cli\u003eSSL-ready (see \u003ca href=\"#ssl-configuration\"\u003einstructions below\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e…\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eGet Started\u003c/h2\u003e\u003ca id=\"user-content-get-started\" class=\"anchor\" aria-label=\"Permalink: Get Started\" href=\"#get-started\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWe strictly support Mac and Ubuntu-based operating systems (we do not support Windows).\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eRequirements\u003c/h3\u003e\u003ca id=\"user-content-requirements\" class=\"anchor\" aria-label=\"Permalink: Requirements\" href=\"#requirements\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003ePlease ensure your operating system has the following software installed:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"https://git-scm.com/\" rel=\"nofollow\"\u003eGit\u003c/a\u003e - see \u003ca href=\"https://help.github.com/articles/set-up-git/\"\u003eGitHub's tutorial\u003c/a\u003e for installation\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"https://nodejs.org\" rel=\"nofollow\"\u003eNode.js\u003c/a\u003e (v10+) - use \u003ca href=\"https://github.com/creationix/nvm\"\u003envm\u003c/a\u003e to install it on any OS\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eAfter installing \u003ccode\u003envm\u003c/code\u003e you will need to run \u003ccode\u003envm install node\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eWe also recommend you install \u003ca href=\"https://yarnpkg.com/\" rel=\"nofollow\"\u003eyarn\u003c/a\u003e, which is an alternative to \u003ca href=\"https://www.npmjs.com/\" rel=\"nofollow\"\u003enpm\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"https://www.mongodb.com/\" rel=\"nofollow\"\u003eMongoDB\u003c/a\u003e (v3.x+):\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eMac (via \u003ca href=\"https://brew.sh/\" rel=\"nofollow\"\u003ebrew\u003c/a\u003e): \u003ccode\u003ebrew tap mongodb/brew \u0026amp;\u0026amp; brew install mongodb-community \u0026amp;\u0026amp; brew services start mongodb-community\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eUbuntu:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6\necho \u0026quot;deb http://repo.mongodb.org/apt/ubuntu \u0026quot;$(lsb_release -sc)\u0026quot;/mongodb-org/3.4 multiverse\u0026quot; | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list\nsudo apt-get update\nsudo apt-get -y install mongodb-org\"\u003e\u003cpre\u003esudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6\n\u003cspan class=\"pl-c1\"\u003eecho\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003edeb http://repo.mongodb.org/apt/ubuntu \u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e$(\u003c/span\u003elsb_release -sc\u003cspan class=\"pl-pds\"\u003e)\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e/mongodb-org/3.4 multiverse\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e \u003cspan class=\"pl-k\"\u003e|\u003c/span\u003e sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list\nsudo apt-get update\nsudo apt-get -y install mongodb-org\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"https://redis.io/\" rel=\"nofollow\"\u003eRedis\u003c/a\u003e (v4.x+):\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eMac (via \u003ca href=\"https://brew.sh/\" rel=\"nofollow\"\u003ebrew\u003c/a\u003e): \u003ccode\u003ebrew install redis \u0026amp;\u0026amp; brew services start redis\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eUbuntu:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"sudo add-apt-repository -y ppa:chris-lea/redis-server\nsudo apt-get update\nsudo apt-get -y install redis-server\"\u003e\u003cpre\u003esudo add-apt-repository -y ppa:chris-lea/redis-server\nsudo apt-get update\nsudo apt-get -y install redis-server\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eInstall\u003c/h3\u003e\u003ca id=\"user-content-install\" class=\"anchor\" aria-label=\"Permalink: Install\" href=\"#install\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"https://www.npmjs.com/\" rel=\"nofollow\"\u003enpm\u003c/a\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"npm install -g lad\"\u003e\u003cpre\u003enpm install -g lad\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"https://yarnpkg.com/\" rel=\"nofollow\"\u003eyarn\u003c/a\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"yarn global add lad\"\u003e\u003cpre\u003eyarn global add lad\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eUsage\u003c/h3\u003e\u003ca id=\"user-content-usage\" class=\"anchor\" aria-label=\"Permalink: Usage\" href=\"#usage\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCreate a project\u003c/h4\u003e\u003ca id=\"user-content-create-a-project\" class=\"anchor\" aria-label=\"Permalink: Create a project\" href=\"#create-a-project\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"lad new-project\ncd new-project\"\u003e\u003cpre\u003elad new-project\n\u003cspan class=\"pl-c1\"\u003ecd\u003c/span\u003e new-project\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDevelopment\u003c/h4\u003e\u003ca id=\"user-content-development\" class=\"anchor\" aria-label=\"Permalink: Development\" href=\"#development\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eTo begin, try typing \u003ccode\u003enpm start\u003c/code\u003e (or \u003ccode\u003eyarn start\u003c/code\u003e) on command line. This will display to you all the scripts you can run.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThe \u003ccode\u003estart\u003c/code\u003e script (among many others) uses \u003ca href=\"https://github.com/kentcdodds/nps\"\u003enps\u003c/a\u003e and \u003ca href=\"https://github.com/kentcdodds/nps-utils\"\u003enps-utils\u003c/a\u003e under the hood. This helps to keep scripts very developer-friendly, and rids the need to write in JSON syntax.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eThis script accepts a \u003ccode\u003e\u0026lt;task\u0026gt;\u003c/code\u003e argument, whereas a task of \u003ccode\u003eall\u003c/code\u003e will spawn, watch, and re-compile all of the \u003ca href=\"#microservices\"\u003emicroservices\u003c/a\u003e mentioned above.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eJust open \u003ca href=\"http://localhost:3000\" rel=\"nofollow\"\u003ehttp://localhost:3000\u003c/a\u003e for testing!\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"https://www.npmjs.com/\" rel=\"nofollow\"\u003enpm\u003c/a\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"npm start all\"\u003e\u003cpre\u003enpm start all\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"https://yarnpkg.com/\" rel=\"nofollow\"\u003eyarn\u003c/a\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"yarn start all\"\u003e\u003cpre\u003eyarn start all\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDebugging\u003c/h5\u003e\u003ca id=\"user-content-debugging\" class=\"anchor\" aria-label=\"Permalink: Debugging\" href=\"#debugging\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eDEBUG\u003c/code\u003e - debug using \u003ca href=\"https://github.com/visionmedia/debug\"\u003edebug\u003c/a\u003e output (widely adopted package in the community for debugging across all Node packages):\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"DEBUG=* ...\"\u003e\u003cpre\u003eDEBUG=\u003cspan class=\"pl-k\"\u003e*\u003c/span\u003e ...\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eNODE_DEBUG\u003c/code\u003e - debug \u003ca href=\"https://nodejs.org\" rel=\"nofollow\"\u003enode\u003c/a\u003e internal modules:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"NODE_DEBUG=* ...\"\u003e\u003cpre\u003eNODE_DEBUG=\u003cspan class=\"pl-k\"\u003e*\u003c/span\u003e ...\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eMONGOOSE_DEBUG\u003c/code\u003e - debug Mongoose raw database operation output:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"MONGOOSE_DEBUG=true ...\"\u003e\u003cpre\u003eMONGOOSE_DEBUG=true ...\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eTRANSPORT_DEBUG\u003c/code\u003e - debug Nodemailer transport:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"TRANSPORT_DEBUG=true ...\"\u003e\u003cpre\u003eTRANSPORT_DEBUG=true ...\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eREDIS_MONITOR\u003c/code\u003e - debug Redis using \u003ccode\u003eMONITOR\u003c/code\u003e (uses \u003ca href=\"https://github.com/ladjs/redis\"\u003e@ladjs/redis\u003c/a\u003e and passes \u003ccode\u003etrue\u003c/code\u003e for the \u003ccode\u003emonitor\u003c/code\u003e argument):\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"REDIS_MONITOR=true ...\"\u003e\u003cpre\u003eREDIS_MONITOR=true ...\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003eREDIS_FRIENDLY_ERROR_STACK\u003c/code\u003e - debug Redis with friendly error stack messages (see \u003ca href=\"https://github.com/luin/ioredis#error-handling\"\u003eshowFriendlyErrorStack\u003c/a\u003e option of \u003ca href=\"https://github.com/luin/ioredis\"\u003eioredis\u003c/a\u003e)\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"REDIS_FRIENDLY_ERROR_STACK=true ...\"\u003e\u003cpre\u003eREDIS_FRIENDLY_ERROR_STACK=true ...\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eProduction\u003c/h4\u003e\u003ca id=\"user-content-production\" class=\"anchor\" aria-label=\"Permalink: Production\" href=\"#production\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWe strongly recommend using \u003ca href=\"https://semaphoreci.com/?ref=lad\" rel=\"nofollow\"\u003eSemaphoreCI\u003c/a\u003e, \u003ca href=\"http://pm2.keymetrics.io/\" rel=\"nofollow\"\u003ePM2\u003c/a\u003e, and \u003ca href=\"https://m.do.co/c/a7fe489d1b27\" rel=\"nofollow\"\u003eDigital Ocean\u003c/a\u003e for production deployment.\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eWe've provided you with a preconfigured \u003ca href=\"/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/ecosystem.json\"\u003eecosystem.json\u003c/a\u003e \u003ca href=\"http://pm2.keymetrics.io/docs/usage/deployment/\" rel=\"nofollow\"\u003edeployment file\u003c/a\u003e. You will need to modify this file with your server's IP, hostname, and other metadata if needed.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eMake sure that your project's assets are built with \u003ccode\u003eNODE_ENV=production\u003c/code\u003e flag, e.g. \u003ccode\u003eNODE_ENV=production npm run build\u003c/code\u003e (or with yarn as \u003ccode\u003eyarn build\u003c/code\u003e);this creates a \u003ccode\u003ebuild/rev-manifest.json\u003c/code\u003e file per \u003ca href=\"https://github.com/niftylettuce/koa-manifest-rev\"\u003ekoa-manifest-rev\u003c/a\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eYou can test this locally by installing \u003ca href=\"http://pm2.keymetrics.io/\" rel=\"nofollow\"\u003ePM2\u003c/a\u003e globally with \u003ca href=\"https://www.npmjs.com/\" rel=\"nofollow\"\u003enpm\u003c/a\u003e or \u003ca href=\"https://yarnpkg.com/\" rel=\"nofollow\"\u003eyarn\u003c/a\u003e, and then running the following command:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"NODE_ENV=production pm2 start\"\u003e\u003cpre\u003eNODE_ENV=production pm2 start\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eSee the \u003ca href=\"#continuous-integration-and-code-coverage\"\u003eContinuous Integration and Code Coverage\u003c/a\u003e and \u003ca href=\"#tutorials\"\u003eTutorials\u003c/a\u003e sections below for instructions on how to setup continuous integration, code coverage, and deployment.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eIf you specify an environment variable value for \u003ccode\u003eAWS_CF_DOMAIN\u003c/code\u003e and \u003ccode\u003eNODE_ENV=production\u003c/code\u003e is set then your assets will need to be published to Amazon S3/Cloudfront. To do so run \u003ccode\u003enpm start publish-assets\u003c/code\u003e (or with yarn as \u003ccode\u003eyarn start publish-assets\u003c/code\u003e). This command automatically sets \u003ccode\u003eNODE_ENV=production\u003c/code\u003e for you as well via \u003ccode\u003ecross-env\u003c/code\u003e.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eProvisioning\u003c/h4\u003e\u003ca id=\"user-content-provisioning\" class=\"anchor\" aria-label=\"Permalink: Provisioning\" href=\"#provisioning\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSee the \u003ca href=\"/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/ansible\"\u003eansible\u003c/a\u003e folder for our \u003ca href=\"https://github.com/ansible/ansible\"\u003eAnsible\u003c/a\u003e configuration and playbooks, which we use to provision servers with.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eWe recommend you to install \u003ca href=\"https://github.com/adrienverge/yamllint\"\u003eyamllint\u003c/a\u003e and configure it in your editor while working with \u003ca href=\"https://github.com/ansible/ansible\"\u003eAnsible\u003c/a\u003e playbooks.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eAlso note that \u003ca href=\"https://github.com/ansible/ansible-lint\"\u003eansible-lint\u003c/a\u003e is a helpful linting tool you can use if you plan on making changes to playbooks. Note that our current playbooks have several existing lint errors.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFirst you must provision Ubuntu 18.04 LTS 64-bit server(s) using \u003ca href=\"https://m.do.co/c/2ffb8129b8d6\" rel=\"nofollow\"\u003eDigital Ocean\u003c/a\u003e, \u003ca href=\"https://www.linode.com/?r=a2840b36770c7020730251a5643428ddbf2e284e\" rel=\"nofollow\"\u003eLinode\u003c/a\u003e, \u003ca href=\"https://www.vultr.com/?ref=7429848\" rel=\"nofollow\"\u003eVultr\u003c/a\u003e, or your host of choice. These newly provisioned server(s) should have your SSH key automatically added.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eFollow the \u003ca href=\"#deployment\"\u003eDeployment\u003c/a\u003e guide below for automatic provisioning and deployment instructions.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDeployment\u003c/h5\u003e\u003ca id=\"user-content-deployment\" class=\"anchor\" aria-label=\"Permalink: Deployment\" href=\"#deployment\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eSet up host configuration by copying the \u003ccode\u003ehosts.yml\u003c/code\u003e file template:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"cp ansible/playbooks/templates/hosts.yml hosts.yml\"\u003e\u003cpre\u003ecp ansible/playbooks/templates/hosts.yml hosts.yml\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eEdit this configuration and update the file with your newly created server aliases and IP addresses. You can add more than one host to each group if you are setting up load balancing. Refer to the \u003ca href=\"#naming-convention\"\u003eNaming Convention\u003c/a\u003e documentation for our recommended approach to server alias naming. Note that this file is automatically ignored by git. If you have a private repository and would like to commit this, then remove \u003ccode\u003ehosts.yml\u003c/code\u003e from the root \u003ccode\u003e.gitignore\u003c/code\u003e file.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"vim hosts.yml\"\u003e\u003cpre\u003evim hosts.yml\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eSet up environment configuration by copying the \u003ccode\u003eenv\u003c/code\u003e file template:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"cp ansible/playbooks/templates/env .env.production\"\u003e\u003cpre\u003ecp ansible/playbooks/templates/env .env.production\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eEdit this configuration and reference the official \u003ca href=\"https://lad.js.org\" rel=\"nofollow\"\u003eLad\u003c/a\u003e documentation for a list of all available environment variables (or see \u003ca href=\"/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.env.defaults\"\u003e.env.defaults\u003c/a\u003e). \u003cstrong\u003eYou will need to open this file in your preferred editor\u003c/strong\u003e and set the values for any fields containing \u003ccode\u003eTODO\u003c/code\u003e, whereby you replace \u003ccode\u003eTODO\u003c/code\u003e with the appropriate value. Preserve double quotes where they are already defined.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"vim .env.production\"\u003e\u003cpre\u003evim .env.production\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eGenerate \u003ca href=\"http://pm2.keymetrics.io/\" rel=\"nofollow\"\u003epm2\u003c/a\u003e \u003ca href=\"https://pm2.keymetrics.io/docs/usage/application-declaration/\" rel=\"nofollow\"\u003eecosystem files\u003c/a\u003e using our automatic template generator. We created an \u003ca href=\"/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/ansible-playbook.js\"\u003eansible-playbook.js\u003c/a\u003e which loads the \u003ccode\u003e.env.production\u003c/code\u003e environment variables rendered with \u003ca href=\"https://github.com/ladjs/env\"\u003e@ladjs/env\u003c/a\u003e into \u003ccode\u003eprocess.env\u003c/code\u003e, which then gets used in the playbooks. This is a superior, simple, and the only known dotenv approach we know of in Ansible. Newly created \u003ccode\u003eecosystem-api.json\u003c/code\u003e, \u003ccode\u003eecosystem-bree.json\u003c/code\u003e, \u003ccode\u003eecosystem-web.json\u003c/code\u003e files will now be created for you in the root of the repository. If you ever more add or change IP addresses, you can simply re-run this command.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"node ansible-playbook ansible/playbooks/ecosystem.yml -l 'localhost'\"\u003e\u003cpre\u003enode ansible-playbook ansible/playbooks/ecosystem.yml -l \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003elocalhost\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eSet up the web and API server(s) (see \u003ca href=\"https://docs.ansible.com/ansible/latest/user_guide/intro_patterns.html#patterns-and-ansible-playbook-flags\" rel=\"nofollow\"\u003epatterns and ansible-playbook flags docs\u003c/a\u003e if you need help). If you completely (or partially) run this playbook (or any others below), then the second time you try to run it may not succeed. This is because we prevent root user access through security hardening. To workaround this, run the same command but without \u003ccode\u003e-e 'ansible_user=root'\u003c/code\u003e appended as it will default to the \u003ccode\u003edevops\u003c/code\u003e user created.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"node ansible-playbook ansible/playbooks/http.yml -e 'ansible_user=root' -l 'http'\"\u003e\u003cpre\u003enode ansible-playbook ansible/playbooks/http.yml -e \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003eansible_user=root\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e -l \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003ehttp\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eSet up the Bree server(s):\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"node ansible-playbook ansible/playbooks/bree.yml -e 'ansible_user=root' -l 'bree'\"\u003e\u003cpre\u003enode ansible-playbook ansible/playbooks/bree.yml -e \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003eansible_user=root\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e -l \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003ebree\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eSet up the Redis server:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"node ansible-playbook ansible/playbooks/redis.yml -e 'ansible_user=root' -l 'redis'\"\u003e\u003cpre\u003enode ansible-playbook ansible/playbooks/redis.yml -e \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003eansible_user=root\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e -l \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003eredis\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eSet up the Mongo server:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"node ansible-playbook ansible/playbooks/mongo.yml -e 'ansible_user=root' -l 'mongo'\"\u003e\u003cpre\u003enode ansible-playbook ansible/playbooks/mongo.yml -e \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003eansible_user=root\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e -l \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003emongo\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eSet up GitHub deployment keys for all the servers. Note that the \u003ccode\u003edeployment-keys\u003c/code\u003e directory is ignored from git, so if you have a private repository and wish to commit it, then remove \u003ccode\u003edeployment-keys\u003c/code\u003e from the \u003ccode\u003e.gitignore\u003c/code\u003e file.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"node ansible-playbook ansible/playbooks/deployment-keys.yml -l 'http:bree'\"\u003e\u003cpre\u003enode ansible-playbook ansible/playbooks/deployment-keys.yml -l \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003ehttp:bree\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eGo to your repository \"Settings\" page on GitHub, click on \"Deploy keys\", and then add a deployment key for each servers' deployment key copied to the \u003ccode\u003edeployment-keys\u003c/code\u003e directory. If you're on macOS, you can use the \u003ccode\u003epbcopy\u003c/code\u003e command to copy each file's contents to your clipboard. Use tab completion for speed, and replace the server names and paths with yours:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"cat deployment-keys/api-1-li-dal.forwardemail.net.pub | pbcopy\n\n#\n# NOTE: repeat the above command for all servers\n# and after running the command, it will copy\n# the key to your clipboard for you to paste as\n# a new deploy key (make sure to use read-only access)\n#\"\u003e\u003cpre\u003ecat deployment-keys/api-1-li-dal.forwardemail.net.pub \u003cspan class=\"pl-k\"\u003e|\u003c/span\u003e pbcopy\n\n\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e NOTE: repeat the above command for all servers\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e and after running the command, it will copy\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e the key to your clipboard for you to paste as\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e a new deploy key (make sure to use read-only access)\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eSet up PM2 deployment directories on all the servers:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"pm2 deploy ecosystem-web.json production setup\"\u003e\u003cpre\u003epm2 deploy ecosystem-web.json production setup\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"pm2 deploy ecosystem-api.json production setup\"\u003e\u003cpre\u003epm2 deploy ecosystem-api.json production setup\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"pm2 deploy ecosystem-bree.json production setup\"\u003e\u003cpre\u003epm2 deploy ecosystem-bree.json production setup\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eCreate a SSL certificate at \u003ca href=\"https://namecheap.com\" rel=\"nofollow\"\u003eNamecheap\u003c/a\u003e (we recommend a 5 year wildcard certificate), set up the certificate, and download and extract the ZIP file with the certificate (emailed to you) to your computer. We do not recommend using tools like \u003ca href=\"https://letsencrypt.org/\" rel=\"nofollow\"\u003eLetsEncrypt\u003c/a\u003e and \u003ccode\u003ecertbot\u003c/code\u003e due to complexity when you have (or scale to) a cluster of servers set up behind load balancers. In other words, we've tried approaches like \u003ccode\u003elsyncd\u003c/code\u003e in combination with \u003ccode\u003ecrontab\u003c/code\u003e for \u003ccode\u003ecertbot\u003c/code\u003e renewals and automatic checking. Furthermore, using this exposes the server(s) to downtime as ports \u003ccode\u003e80\u003c/code\u003e and \u003ccode\u003e443\u003c/code\u003e may need to be shut down so that \u003ccode\u003ecertbot\u003c/code\u003e can use them for certificate generation. This is not a reliable approach, and simply renewing certificates once a year is vastly simpler and also makes using load balancers trivial. Instead you can use a provider like \u003ca href=\"https://namecheap.com\" rel=\"nofollow\"\u003eNamecheap\u003c/a\u003e to get a cheap SSL certificate, then run a few commands as we've documented below. This command will prompt you for an absolute file path to the certificates you downloaded. Renewed your certificate after 1 year? Simply follow this step again. Do not set a password on the certificate files. When using the \u003ccode\u003eopenssl\u003c/code\u003e command (see Namecheap instructions), you need to use \u003ccode\u003e*.example.com\u003c/code\u003e with an asterisk followed by a period if you are registering a wildcard certificate.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"ansible-playbook ansible/playbooks/certificates.yml\"\u003e\u003cpre\u003eansible-playbook ansible/playbooks/certificates.yml\u003c/pre\u003e\u003c/div\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eImportant:\u003c/strong\u003e If you renew or change certificates in the future, then after running the previous command, you will subsequently need to reload the processes as such:\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"#\n# NOTE: See the \u0026quot;Important\u0026quot; note above BEFORE running this command.\n# This command ONLY APPLIES for certificate renewals/changes.\n#\npm2 deploy ecosystem-web.json production exec \u0026quot;pm2 reload web\u0026quot;\npm2 deploy ecosystem-api.json production exec \u0026quot;pm2 reload api\u0026quot;\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e NOTE: See the \"Important\" note above BEFORE running this command.\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e This command ONLY APPLIES for certificate renewals/changes.\u003c/span\u003e\n\u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e\u003c/span\u003e\npm2 deploy ecosystem-web.json production \u003cspan class=\"pl-c1\"\u003eexec\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003epm2 reload web\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\npm2 deploy ecosystem-api.json production \u003cspan class=\"pl-c1\"\u003eexec\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003epm2 reload api\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e(Optional) Create a Google application credentials profile file and store it locally. You only need this if you want to support automatic translation. The following command will prompt you for the absolute file path (e.g. \u003ccode\u003e/path/to/client-profile.json\u003c/code\u003e). See the \u003ca href=\"https://github.com/niftylettuce/mandarin\"\u003emandarin\u003c/a\u003e docs for more information.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"ansible-playbook ansible/playbooks/gapp-creds.yml -l 'http:bree'\"\u003e\u003cpre\u003eansible-playbook ansible/playbooks/gapp-creds.yml -l \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003ehttp:bree\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eCopy the \u003ccode\u003e.env.production\u003c/code\u003e file and create an AWS config file on the servers:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"node ansible-playbook ansible/playbooks/env.yml -l 'http:bree'\"\u003e\u003cpre\u003enode ansible-playbook ansible/playbooks/env.yml -l \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003ehttp:bree\u003cspan class=\"pl-pds\"\u003e'\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eRun an initial deploy to all the servers:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"pm2 deploy ecosystem-web.json production\"\u003e\u003cpre\u003epm2 deploy ecosystem-web.json production\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"pm2 deploy ecosystem-api.json production\"\u003e\u003cpre\u003epm2 deploy ecosystem-api.json production\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"pm2 deploy ecosystem-bree.json production\"\u003e\u003cpre\u003epm2 deploy ecosystem-bree.json production\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eSave the process list on the servers so when if the server were to reboot, it will automatically boot back up the processes:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"pm2 deploy ecosystem-web.json production exec \u0026quot;pm2 save\u0026quot;\"\u003e\u003cpre\u003epm2 deploy ecosystem-web.json production \u003cspan class=\"pl-c1\"\u003eexec\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003epm2 save\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"pm2 deploy ecosystem-api.json production exec \u0026quot;pm2 save\u0026quot;\"\u003e\u003cpre\u003epm2 deploy ecosystem-api.json production \u003cspan class=\"pl-c1\"\u003eexec\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003epm2 save\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"pm2 deploy ecosystem-bree.json production exec \u0026quot;pm2 save\u0026quot;\"\u003e\u003cpre\u003epm2 deploy ecosystem-bree.json production \u003cspan class=\"pl-c1\"\u003eexec\u003c/span\u003e \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003epm2 save\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eTest by visiting your web and API server in your browser (click \"proceed to unsafe\" site and bypass certificate warning).\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eConfigure your DNS records for the web and API server hostnames and respective IP addresses.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eTest by visiting your web and API server in your browser (in an incognito window). There should not be any certificate warnings (similar to the one that occurred in step 15).\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e(Optional) Remove the local \u003ccode\u003e.env.production\u003c/code\u003e file for security purposes. If you do this, then make sure you have a backup, or securely back up off the server in the future before destroying the server.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"rm .env.production\"\u003e\u003cpre\u003erm .env.production\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003e(Optional) Remove the local certificate files you downloaded locally and specified in step 11. If you do this, then make sure you have a backup, or securely back up off the server in the future before destroying the server.\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eFinished. If you need to deploy again, then push your changes to GitHub \u003ccode\u003emaster\u003c/code\u003e branch and then follow step 14 again. We recommend you to read the \u003ca href=\"https://docs.ansible.com/ansible/latest/user_guide/intro_getting_started.html\" rel=\"nofollow\"\u003eAnsible getting started guide\u003c/a\u003e, as it provides you with insight into commands like \u003ccode\u003eansible all -a \"echo hello\"\u003c/code\u003e which can be run across all or specific servers.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTests\u003c/h4\u003e\u003ca id=\"user-content-tests\" class=\"anchor\" aria-label=\"Permalink: Tests\" href=\"#tests\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWe use \u003ca href=\"https://github.com/avajs/ava\"\u003eava\u003c/a\u003e and \u003ca href=\"https://github.com/istanbuljs/nyc\"\u003enyc\u003c/a\u003e for testing and code coverage.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"https://www.npmjs.com/\" rel=\"nofollow\"\u003enpm\u003c/a\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"npm test\"\u003e\u003cpre\u003enpm \u003cspan class=\"pl-c1\"\u003etest\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"https://yarnpkg.com/\" rel=\"nofollow\"\u003eyarn\u003c/a\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"yarn test\"\u003e\u003cpre\u003eyarn \u003cspan class=\"pl-c1\"\u003etest\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eConfiguration\u003c/h3\u003e\u003ca id=\"user-content-configuration\" class=\"anchor\" aria-label=\"Permalink: Configuration\" href=\"#configuration\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eEnvironment Variables\u003c/h4\u003e\u003ca id=\"user-content-environment-variables\" class=\"anchor\" aria-label=\"Permalink: Environment Variables\" href=\"#environment-variables\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWe have made configuration of your Lad project easy through a \u003ca href=\"https://github.com/motdotla/dotenv\"\u003edotenv\u003c/a\u003e configuration package called \u003ca href=\"https://github.com/ladjs/env\"\u003e@ladjs/env\u003c/a\u003e, per \u003ca href=\"https://12factor.net/\" rel=\"nofollow\"\u003eTwelve-Factor\u003c/a\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eWe use the following three packages to manage configuration:\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/niftylettuce/node-dotenv-extended\"\u003edotenv-extended\u003c/a\u003e - allows us to craft a \u003ccode\u003e.env\u003c/code\u003e definition (otherwise known as a \"schema\") in a file named \u003ccode\u003e.env.schema\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/janl/mustache.js/\"\u003emustache\u003c/a\u003e - allows us to use the \u003ca href=\"https://github.com/janl/mustache.js/\"\u003eMustache templating language\u003c/a\u003e in our \u003ccode\u003e.env\u003c/code\u003e and \u003ccode\u003e.env.defaults\u003c/code\u003e configuration files\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/niftylettuce/dotenv-parse-variables\"\u003edotenv-parse-variables\u003c/a\u003e - automatically parses variable types from \u003ccode\u003eprocess.env\u003c/code\u003e (e.g. \u003ccode\u003eFOO=4\u003c/code\u003e will set \u003ccode\u003eprocess.env.FOO = 4\u003c/code\u003e with a \u003ccode\u003eNumber\u003c/code\u003e variable type instead of a \u003ccode\u003eString\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp dir=\"auto\"\u003eConfiguration is managed by the following, in order of priority:\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003eContents of the file at \u003ccode\u003econfig/index.js\u003c/code\u003e (reads in \u003ccode\u003eprocess.env\u003c/code\u003e environment variables)\u003c/li\u003e\n\u003cli\u003eContents of the files in directories under \u003ccode\u003econfig/environments/\u003c/code\u003e (sets defaults per environment, e.g. you can pass \u003ccode\u003eNODE_ENV=staging\u003c/code\u003e and it will load the file at \u003ccode\u003econfig/environments/staging.js\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003eEnvironment variables used to override defaults or set required ones (e.g. \u003ccode\u003eNODE_ENV=production\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003eEnvironment configuration in \u003ccode\u003e.env\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eEnvironment configuration in \u003ccode\u003e.env.defaults\u003c/code\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp dir=\"auto\"\u003ePrecedence is taken by the environment configuration files, environment variables, then the \u003ccode\u003e.env\u003c/code\u003e file.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eBasically \u003ca href=\"https://github.com/motdotla/dotenv\"\u003edotenv\u003c/a\u003e won't set an environment variable if it already detects it was passed as an environment variable.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eTake a look at the \u003ca href=\"/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/config\"\u003econfig\u003c/a\u003e folder contents and also at the defaults at \u003ca href=\"/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/.env.defaults\"\u003e.env.defaults\u003c/a\u003e.\u003c/p\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eNODE_ENV\u003c/code\u003e - (options: \u003ccode\u003edevelopment\u003c/code\u003e, \u003ccode\u003eproduction\u003c/code\u003e default: \u003ccode\u003edevelopment\u003c/code\u003e) - the node environment the app is running in\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ePROXY_PORT\u003c/code\u003e - (default: \u003ccode\u003e8080\u003c/code\u003e) - proxy port used to proxy requests (see \u003ca href=\"https://github.com/ladjs/proxy\"\u003eladjs/proxy\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eHTTP_PROTOCOL\u003c/code\u003e - (defaults: \u003ccode\u003ehttp\u003c/code\u003e recommend: \u003ccode\u003ehttps\u003c/code\u003e) - protocol used for http requests\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eHTTP_PORT\u003c/code\u003e - (defaults: \u003ccode\u003e80\u003c/code\u003e recommend: \u003ccode\u003e443\u003c/code\u003e) - http port used for http requests\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_PROTOCOL\u003c/code\u003e - (default: \u003ccode\u003ehttp\u003c/code\u003e) - \u003ca href=\"https://github.com/ladjs/web\"\u003eladjs/web\u003c/a\u003e application protocol\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_HOST\u003c/code\u003e - (default: \u003ccode\u003elocalhost\u003c/code\u003e) - \u003ca href=\"https://github.com/ladjs/web\"\u003eladjs/web\u003c/a\u003e application host\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_PORT\u003c/code\u003e - (default: \u003ccode\u003e3000\u003c/code\u003e) - \u003ca href=\"https://github.com/ladjs/web\"\u003eladjs/web\u003c/a\u003e application port\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_URL\u003c/code\u003e - (default: \u003ccode\u003e{{WEB_PROTOCOL}}://{{WEB_HOST}}:{{WEB_PORT}}\u003c/code\u003e) - web application absolute URI\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_SSL_KEY_PATH\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/web\"\u003eladjs/web\u003c/a\u003e file path to your SSL key file\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_SSL_CERT_PATH\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/web\"\u003eladjs/web\u003c/a\u003e file path to your SSL certificate file\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_SSL_CA_PATH\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/web\"\u003eladjs/web\u003c/a\u003e file path to your SSL certificate authority file\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_HOST\u003c/code\u003e - (default: \u003ccode\u003elocalhost\u003c/code\u003e) - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e host\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_PORT\u003c/code\u003e - (default: \u003ccode\u003e4000\u003c/code\u003e) - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e port\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_PROTOCOL\u003c/code\u003e - (default: \u003ccode\u003ehttp\u003c/code\u003e recommend: \u003ccode\u003ehttps\u003c/code\u003e) - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e protocol\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_URL\u003c/code\u003e - (default: \u003ccode\u003e{{API_PROTOCOL}}://{{API_HOST}}:{{API_PORT}}\u003c/code\u003e) - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e absolute URI\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_SSL_KEY_PATH\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e file path to your SSL key file\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_SSL_CERT_PATH\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e file path to your SSL certificate file\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_SSL_CA_PATH\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e file path to your SSL certificate authority file\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_RATELIMIT_WHITELIST\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e ratelimiter whitelisted ips (see: \u003ca href=\"https://github.com/scttcper/koa-simple-ratelimit\"\u003ekoa-simple-ratelimit\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPP_NAME\u003c/code\u003e - (default: \u003ccode\u003eLad\u003c/code\u003e) - application name (see \u003ca href=\"https://github.com/search?p=3\u0026amp;q=org%3Aladjs+appName\u0026amp;type=Code\"\u003eusage\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPP_COLOR\u003c/code\u003e - application color theme (see \u003ca href=\"https://github.com/search?q=org%3Aladjs+appColor\u0026amp;type=Code\"\u003eusage\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eTWITTER\u003c/code\u003e - (default: \u003ccode\u003e@niftylettuce\u003c/code\u003e) twitter handle\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eSEND_EMAIL\u003c/code\u003e - (default: \u003ccode\u003efalse\u003c/code\u003e) - whether to send email or preview (see \u003ca href=\"https://github.com/ladjs/lad#outbound-email-configuration\"\u003eoutbound email configuration\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eTRANSPORT_DEBUG\u003c/code\u003e - (default: \u003ccode\u003efalse\u003c/code\u003e) - email transport debug logging (see \u003ca href=\"https://github.com/ladjs/lad#debugging\"\u003edebugging\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eEMAIL_DEFAULT_FROM\u003c/code\u003e - (default: \u003ccode\u003esupport@127.0.01\u003c/code\u003e) - default email \u003ccode\u003efrom\u003c/code\u003e address\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eSHOW_STACK\u003c/code\u003e - (default: \u003ccode\u003etrue\u003c/code\u003e) - whether or not to output a stack trace when logging (see \u003ca href=\"https://github.com/cabinjs/axe#options\"\u003ecabinjs options\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eSHOW_META\u003c/code\u003e - (default: \u003ccode\u003etrue\u003c/code\u003e) - whether or not to output metadata to logger methods (see \u003ca href=\"https://github.com/cabinjs/axe#options\"\u003ecabinjs options\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eSUPPORT_REQUEST_MAX_LENGTH\u003c/code\u003e - (default: \u003ccode\u003e500\u003c/code\u003e) - support request max message size in characters\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eERROR_HANDLER_BASE_URL\u003c/code\u003e - (default: \u003ccode\u003e{{WEB_URL}}\u003c/code\u003e) error handling base url (see \u003ca href=\"https://github.com/ladjs/koa-better-error-handler\"\u003ekoa-better-error-handler\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eI18N_SYNC_FILES\u003c/code\u003e - (default: \u003ccode\u003etrue\u003c/code\u003e) - sync locale information across all files (see \u003ca href=\"https://github.com/ladjs/i18n#options\"\u003eladjs/i18n options\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eI18N_AUTO_RELOAD\u003c/code\u003e - (default: \u003ccode\u003efalse\u003c/code\u003e) - watch for changes in json files to reload locale on updates (see \u003ca href=\"https://github.com/ladjs/i18n#options\"\u003eladjs/i18n options\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eI18N_UPDATE_FILES\u003c/code\u003e - (default: \u003ccode\u003etrue\u003c/code\u003e) - write new locale information to disk (see \u003ca href=\"https://github.com/ladjs/i18n#options\"\u003eladjs/i18n options\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAUTH_LOCAL_ENABLED\u003c/code\u003e - (default: \u003ccode\u003etrue\u003c/code\u003e) - enable passport local strategy (see \u003ca href=\"https://github.com/ladjs/passport\"\u003eladjs/passport\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAUTH_FACEBOOK_ENABLED\u003c/code\u003e - (default: \u003ccode\u003efalse\u003c/code\u003e) - enable authenticating with Facebook using the OAuth 2.0 (see \u003ca href=\"https://github.com/ladjs/passport\"\u003eladjs/passport\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAUTH_TWITTER_ENABLED\u003c/code\u003e - (default: \u003ccode\u003efalse\u003c/code\u003e) - enable authenticating with Twitter using the OAuth 1.0 (see \u003ca href=\"https://github.com/ladjs/passport\"\u003eladjs/passport\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAUTH_GOOGLE_ENABLED\u003c/code\u003e - (default: \u003ccode\u003efalse\u003c/code\u003e) - enable authenticating with Google using OAuth 2.0 (see \u003ca href=\"https://github.com/ladjs/lad#google-auth\"\u003egoogle auth\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAUTH_GITHUB_ENABLED\u003c/code\u003e - (default: \u003ccode\u003efalse\u003c/code\u003e) - enable authenticating with Github using OAuth 2.0 (see \u003ca href=\"https://github.com/ladjs/passport\"\u003eladjs/passport\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAUTH_LINKEDIN_ENABLED\u003c/code\u003e - (default: \u003ccode\u003efalse\u003c/code\u003e) - enable authenticating with LinkedIn using OAuth 1.0 (see \u003ca href=\"https://github.com/ladjs/passport\"\u003eladjs/passport\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAUTH_INSTAGRAM_ENABLED\u003c/code\u003e - (default: \u003ccode\u003efalse\u003c/code\u003e) - enable authenticating with Instagram using OAuth 2.0 (see \u003ca href=\"https://github.com/ladjs/passport\"\u003eladjs/passport\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAUTH_OTP_ENABLED\u003c/code\u003e - (default: \u003ccode\u003efalse\u003c/code\u003e) - enable authenticating with OTP, a form of two-factor authentication (see \u003ca href=\"https://github.com/ladjs/passport\"\u003eladjs/passport\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAUTH_STRIPE_ENABLED\u003c/code\u003e - (default: false) - enable authenticating with Stripe using OAuth 2.0 (see \u003ca href=\"https://github.com/ladjs/passport\"\u003eladjs/passport\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eGOOGLE_CLIENT_ID\u003c/code\u003e - google oauth2 client id (see \u003ca href=\"https://github.com/ladjs/lad#google-auth\"\u003egoogle auth\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eGOOGLE_CLIENT_SECRET\u003c/code\u003e - google oauth2 secret (see \u003ca href=\"https://github.com/ladjs/lad#google-auth\"\u003egoogle auth\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eGOOGLE_CALLBACK_URL\u003c/code\u003e - google oauth2 callback url (see \u003ca href=\"https://github.com/ladjs/lad#google-auth\"\u003egoogle auth\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eGOOGLE_APPLICATION_CREDENTIALS\u003c/code\u003e - path to google cloud platform credentials (see \u003ca href=\"https://cloud.google.com/docs/authentication/getting-started\" rel=\"nofollow\"\u003egcp credentials\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eGITHUB_CLIENT_ID\u003c/code\u003e - github oauth client id (see \u003ca href=\"https://github.com/ladjs/passport\"\u003eladjs/passport\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eGITHUB_CLIENT_SECRET\u003c/code\u003e - github oauth secret (see \u003ca href=\"https://github.com/ladjs/passport\"\u003eladjs/passport\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eGITHUB_CALLBACK_URL\u003c/code\u003e - github oauth callback URL (see \u003ca href=\"https://github.com/ladjs/passport\"\u003eladjs/passport\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ePOSTMARK_API_TOKEN\u003c/code\u003e - postmark api token (see \u003ca href=\"https://github.com/ladjs/lad#outbound-email-configuration\"\u003eoutbound email configuration\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eCODECOV_TOKEN\u003c/code\u003e - codecov api token (see \u003ca href=\"https://github.com/ladjs/lad#continuous-integration-and-code-coverage\"\u003econtinuous integration and code coverage\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eMONGO_USER\u003c/code\u003e - mongodb username\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eMONGO_PASS\u003c/code\u003e - mongodb password\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eMONGO_HOST\u003c/code\u003e - (default: \u003ccode\u003elocalhost\u003c/code\u003e) - mongodb hostname\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eMONGO_PORT\u003c/code\u003e - (default: \u003ccode\u003e27017\u003c/code\u003e) - mongodb port\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eMONGO_NAME\u003c/code\u003e - (default: \u003ccode\u003e{{APP_NAME}}_{{NODE_ENV}}\u003c/code\u003e) - mongodb name\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eMONGO_URI\u003c/code\u003e - (default: \u003ccode\u003emongodb://{{MONGO_HOST}}:{{MONGO_PORT}}/{{MONGO_NAME}}\u003c/code\u003e) - mongodb connection URI\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_MONGO_USER\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/web\"\u003eladjs/web\u003c/a\u003e mongodb username\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_MONGO_PASS\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/web\"\u003eladjs/web\u003c/a\u003e mongodb password\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_MONGO_HOST\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/web\"\u003eladjs/web\u003c/a\u003e mongodb hostname\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_MONGO_NAME\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/web\"\u003eladjs/web\u003c/a\u003e mongodb name\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_MONGO_PORT\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/web\"\u003eladjs/web\u003c/a\u003e mongodb port\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_MONGO_URI\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/web\"\u003eladjs/web\u003c/a\u003e mongodb connection URI\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_MONGO_USER\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e mongodb username\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_MONGO_PASS\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e mongodb password\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_MONGO_HOST\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e mongodb hostname\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_MONGO_NAME\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e mongodb name\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_MONGO_PORT\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e mongodb port\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_MONGO_URI\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e mongodb connection URI\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eBREE_MONGO_USER\u003c/code\u003e - \u003ca href=\"https://github.com/breejs/bree\"\u003ebreejs/bree\u003c/a\u003e mongodb username\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eBREE_MONGO_PASS\u003c/code\u003e - \u003ca href=\"https://github.com/breejs/bree\"\u003ebreejs/bree\u003c/a\u003e mongodb password\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eBREE_MONGO_HOST\u003c/code\u003e - \u003ca href=\"https://github.com/breejs/bree\"\u003ebreejs/bree\u003c/a\u003e mongodb hostname\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eBREE_MONGO_NAME\u003c/code\u003e - \u003ca href=\"https://github.com/breejs/bree\"\u003ebreejs/bree\u003c/a\u003e mongodb name\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eBREE_MONGO_PORT\u003c/code\u003e - \u003ca href=\"https://github.com/breejs/bree\"\u003ebreejs/bree\u003c/a\u003e mongodb port\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eBREE_MONGO_URI\u003c/code\u003e - \u003ca href=\"https://github.com/breejs/bree\"\u003ebreejs/bree\u003c/a\u003e mongodb connection URI\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eREDIS_PORT\u003c/code\u003e - (default: \u003ccode\u003e6379\u003c/code\u003e) - redis port\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eREDIS_HOST\u003c/code\u003e - (default: \u003ccode\u003elocalhost\u003c/code\u003e) - redis hostname\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eREDIS_PASSWORD\u003c/code\u003e - redis password\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_REDIS_PORT\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/web\"\u003eladjs/web\u003c/a\u003e redis port\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_REDIS_HOST\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/web\"\u003eladjs/web\u003c/a\u003e redis hostname\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_REDIS_PASSWORD\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/web\"\u003eladjs/web\u003c/a\u003e redis password\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_REDIS_PORT\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e redis port\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_REDIS_HOST\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e redis hostname\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_REDIS_PASSWORD\u003c/code\u003e - \u003ca href=\"https://github.com/ladjs/api\"\u003eladjs/api\u003c/a\u003e redis password\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eBREE_REDIS_PORT\u003c/code\u003e - \u003ca href=\"https://github.com/breejs/bree\"\u003ebreejs/bree\u003c/a\u003e redis port\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eBREE_REDIS_HOST\u003c/code\u003e - \u003ca href=\"https://github.com/breejs/bree\"\u003ebreejs/bree\u003c/a\u003e redis hostname\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eBREE_REDIS_PASSWORD\u003c/code\u003e - \u003ca href=\"https://github.com/breejs/bree\"\u003ebreejs/bree\u003c/a\u003e redis password\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eMANDARIN_REDIS_PORT\u003c/code\u003e - \u003ca href=\"https://github.com/niftylettuce/mandarin\"\u003emandarin\u003c/a\u003e redis port\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eMANDARIN_REDIS_HOST\u003c/code\u003e - \u003ca href=\"https://github.com/niftylettuce/mandarin\"\u003emandarin\u003c/a\u003e redis hostname\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eMANDARIN_REDIS_PASSWORD\u003c/code\u003e - \u003ca href=\"https://github.com/niftylettuce/mandarin\"\u003emandarin\u003c/a\u003e redis password\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eCERTBOT_WELL_KNOWN_NAME\u003c/code\u003e - letsencrypt wellknown name (see \u003ca href=\"https://certbot.eff.org/docs/using.html#id11\" rel=\"nofollow\"\u003ecertbot options\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eCERTBOT_WELL_KNOWN_CONTENTS\u003c/code\u003e - letsencrypt wellknown contents (see \u003ca href=\"https://certbot.eff.org/docs/using.html#id11\" rel=\"nofollow\"\u003ecertbot options\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eVERIFICATION_PIN_TIMEOUT_MS\u003c/code\u003e - (default: \u003ccode\u003e5m\u003c/code\u003e) - email verification pin expiry\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eVERIFICATION_PIN_EMAIL_INTERVAL_MS\u003c/code\u003e - (default: \u003ccode\u003e1m\u003c/code\u003e) - email verification pin email interval\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_SECRETS\u003c/code\u003e - (default: \u003ccode\u003esecret\u003c/code\u003e) - list of restricted api secrets\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eCACHE_RESPONSES\u003c/code\u003e - (default: \u003ccode\u003efalse\u003c/code\u003e) - cache specified responses (see \u003ca href=\"https://github.com/ladjs/koa-cache-responses\"\u003eladjs/koa-cache-responses\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eSLACK_API_TOKEN\u003c/code\u003e - slack api token (see \u003ca href=\"https://slack.dev/node-slack-sdk/web-api\" rel=\"nofollow\"\u003eslack web api\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eSSL Configuration\u003c/h4\u003e\u003ca id=\"user-content-ssl-configuration\" class=\"anchor\" aria-label=\"Permalink: SSL Configuration\" href=\"#ssl-configuration\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eTo configure SSL for the web or API server simply set them in your \u003ccode\u003e.env\u003c/code\u003e file or pass them as environment variables.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003eWeb server:\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eWEB_PROTOCOL\u003c/code\u003e - you must set this to \u003ccode\u003ehttps\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_SSL_KEY_PATH\u003c/code\u003e - file path to your SSL key file (e.g. \u003ccode\u003e/home/deploy/.ssl/web-key.pem\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_SSL_CERT_PATH\u003c/code\u003e - file path to your SSL certificate file (e.g. \u003ccode\u003e/home/deploy/.ssl/web-cert.pem\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eWEB_SSL_CA_PATH\u003c/code\u003e (optional) - file path to your SSL certificate authority file (e.g. \u003ccode\u003e/home/deploy/.ssl/web-ca-cert.pem\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003eAPI server:\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003eAPI_PROTOCOL\u003c/code\u003e - you must set this to \u003ccode\u003ehttps\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_SSL_KEY_PATH\u003c/code\u003e - file path to your SSL key file (e.g. \u003ccode\u003e/home/deploy/.ssl/api-key.pem\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_SSL_CERT_PATH\u003c/code\u003e - file path to your SSL certificate file (e.g. \u003ccode\u003e/home/deploy/.ssl/api-cert.pem\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eAPI_SSL_CA_PATH\u003c/code\u003e (optional) - file path to your SSL certificate authority file (e.g. \u003ccode\u003e/home/deploy/.ssl/api-ca-cert.pem\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eOutbound Email Configuration\u003c/h4\u003e\u003ca id=\"user-content-outbound-email-configuration\" class=\"anchor\" aria-label=\"Permalink: Outbound Email Configuration\" href=\"#outbound-email-configuration\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eBy default in the development environment we simply render the email in your browser.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eHowever in other environments such as production, you definitely want emails to be sent.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eWe built-in support for Postmark by default (though you can swap in your own \u003ccode\u003etransport\u003c/code\u003e provider in the \u003ccode\u003ejobs/email.js\u003c/code\u003e file):\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eGo to \u003ca href=\"https://postmarkapp.com?utm_source=lad\" rel=\"nofollow\"\u003ehttps://postmarkapp.com\u003c/a\u003e – Start Free Trial\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eCreate a free trial account, then click Get Started, and proceed to create a \"Server\" and \"Sender Signature\"\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eCopy/paste the \"Server API token\" under \"Credentials\" in your \u003ccode\u003e.env\u003c/code\u003e file (example below)\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-diff notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"-POSTMARK_API_TOKEN=\n+POSTMARK_API_TOKEN=ac6657eb-2732-4cfd-915b-912b1b10beb1\"\u003e\u003cpre\u003e\u003cspan class=\"pl-md\"\u003e\u003cspan class=\"pl-md\"\u003e-\u003c/span\u003ePOSTMARK_API_TOKEN=\u003c/span\u003e\n\u003cspan class=\"pl-mi1\"\u003e\u003cspan class=\"pl-mi1\"\u003e+\u003c/span\u003ePOSTMARK_API_TOKEN=ac6657eb-2732-4cfd-915b-912b1b10beb1\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eModify the \u003ccode\u003eSEND_EMAIL\u003c/code\u003e variable in \u003ccode\u003e.env\u003c/code\u003e from \u003ccode\u003efalse\u003c/code\u003e to \u003ccode\u003etrue\u003c/code\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eFavicon and Touch Icon Configuration\u003c/h4\u003e\u003ca id=\"user-content-favicon-and-touch-icon-configuration\" class=\"anchor\" aria-label=\"Permalink: Favicon and Touch Icon Configuration\" href=\"#favicon-and-touch-icon-configuration\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eYou can customize the favicon and touch icons – just generate a new set at \u003ca href=\"https://realfavicongenerator.net\" rel=\"nofollow\"\u003ehttps://realfavicongenerator.net\u003c/a\u003e and overwrite the existing in the \u003ca href=\"/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/assets\"\u003eassets\u003c/a\u003e folder.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eJust make sure that any relative paths match up in the \u003ccode\u003eassets/browserconfig.xml\u003c/code\u003e and \u003ccode\u003eassets/manifest.json\u003c/code\u003e files.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eAuthentication Methods\u003c/h4\u003e\u003ca id=\"user-content-authentication-methods\" class=\"anchor\" aria-label=\"Permalink: Authentication Methods\" href=\"#authentication-methods\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWe use Lad's auth package under the hood; so if you want to configure authentication providers you'll want to read more or contribute to \u003ca href=\"https://github.com/ladjs/auth\"\u003e@ladjs/auth\u003c/a\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch5 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eGoogle Auth\u003c/h5\u003e\u003ca id=\"user-content-google-auth\" class=\"anchor\" aria-label=\"Permalink: Google Auth\" href=\"#google-auth\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIn order to add Google sign-in to your app (so users can log in with their Google account):\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eGo to \u003ca href=\"https://console.developers.google.com\" rel=\"nofollow\"\u003ehttps://console.developers.google.com\u003c/a\u003e – Create a project (and fill out your project information – if you need a 120x120px default image, \u003ca href=\"https://cdn.rawgit.com/ladjs/lad/82d38d64/media/lad-120x120.png\" rel=\"nofollow\"\u003eyou can use this one\u003c/a\u003e with a CDN path of \u003ca href=\"https://cdn.rawgit.com/ladjs/lad/82d38d64/media/lad-120x120.png\" rel=\"nofollow\"\u003ehttps://cdn.rawgit.com/ladjs/lad/82d38d64/media/lad-120x120.png\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eUnder your newly created project, go to Credentials – Create credentials – OAuth client ID – Web application\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eSet \"Authorized JavaScript origins\" to \u003ccode\u003ehttp://yourdomain.com\u003c/code\u003e (replace with your domain) and also \u003ccode\u003ehttp://localhost:3000\u003c/code\u003e (for local development)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eSet \"Authorized redirect URIs\" to \u003ccode\u003ehttp://yourdomain.com/auth/google/ok\u003c/code\u003e (again, replace with your domain) and also \u003ccode\u003ehttp://localhost:3000/auth/google/ok\u003c/code\u003e (again, for local development)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eCopy and paste the newly created key pair for respective properties in your \u003ccode\u003e.env\u003c/code\u003e file (example below)\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-diff notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"-GOOGLE_CLIENT_ID=\n+GOOGLE_CLIENT_ID=424623312719-73vn8vb4tmh8nht96q7vdbn3mc9pd63a.apps.googleusercontent.com\n-GOOGLE_CLIENT_SECRET=\n+GOOGLE_CLIENT_SECRET=Oys6WrHleTOksqXTbEY_yi07\"\u003e\u003cpre\u003e\u003cspan class=\"pl-md\"\u003e\u003cspan class=\"pl-md\"\u003e-\u003c/span\u003eGOOGLE_CLIENT_ID=\u003c/span\u003e\n\u003cspan class=\"pl-mi1\"\u003e\u003cspan class=\"pl-mi1\"\u003e+\u003c/span\u003eGOOGLE_CLIENT_ID=424623312719-73vn8vb4tmh8nht96q7vdbn3mc9pd63a.apps.googleusercontent.com\u003c/span\u003e\n\u003cspan class=\"pl-md\"\u003e\u003cspan class=\"pl-md\"\u003e-\u003c/span\u003eGOOGLE_CLIENT_SECRET=\u003c/span\u003e\n\u003cspan class=\"pl-mi1\"\u003e\u003cspan class=\"pl-mi1\"\u003e+\u003c/span\u003eGOOGLE_CLIENT_SECRET=Oys6WrHleTOksqXTbEY_yi07\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eIn \u003ccode\u003e.env\u003c/code\u003e, make sure that \u003ccode\u003eAUTH_GOOGLE_ENABLED=true\u003c/code\u003e to enable this authentication method.\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTranslation Configuration\u003c/h4\u003e\u003ca id=\"user-content-translation-configuration\" class=\"anchor\" aria-label=\"Permalink: Translation Configuration\" href=\"#translation-configuration\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003eGo to \u003ca href=\"https://console.developers.google.com\" rel=\"nofollow\"\u003ehttps://console.developers.google.com\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eEnable the Google Translate API\u003c/li\u003e\n\u003cli\u003eCopy your API key and set it as the environment variable \u003ccode\u003eGOOGLE_TRANSLATE_KEY=******\u003c/code\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eContinuous Integration and Code Coverage\u003c/h4\u003e\u003ca id=\"user-content-continuous-integration-and-code-coverage\" class=\"anchor\" aria-label=\"Permalink: Continuous Integration and Code Coverage\" href=\"#continuous-integration-and-code-coverage\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eWe strongly recommend that you use \u003ca href=\"https://semaphoreci.com/?ref=lad\" rel=\"nofollow\"\u003eSemaphoreCI\u003c/a\u003e for continuous integration and \u003ca href=\"https://codecov.io/gh\" rel=\"nofollow\"\u003eCodecov\u003c/a\u003e for code coverage.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eHere are the simple steps required to setup \u003ca href=\"https://semaphoreci.com/?ref=lad\" rel=\"nofollow\"\u003eSemaphoreCI\u003c/a\u003e with \u003ca href=\"https://codecov.io/gh\" rel=\"nofollow\"\u003eCodecov\u003c/a\u003e:\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eGo to \u003ca href=\"https://semaphoreci.com/?ref=lad\" rel=\"nofollow\"\u003eSemaphoreCI\u003c/a\u003e and sign up for a free account\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eOnce your repository is pushed to GitHub, add it as a project on SemaphoreCI\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eConfigure your project on SemaphoreCI with the following build settings:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003eReplace \u003ccode\u003enpm\u003c/code\u003e with \u003ccode\u003eyarn\u003c/code\u003e if you're using \u003ca href=\"https://yarnpkg.com/\" rel=\"nofollow\"\u003eyarn\u003c/a\u003e as your package manager\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eLanguage: \u003ccode\u003eJavaScript\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eNode.js version: \u003ccode\u003e10+\u003c/code\u003e (latest LTS)\n\u003cblockquote\u003e\n\u003cp dir=\"auto\"\u003eNote you can also add to \u003ccode\u003eSetup\u003c/code\u003e the script \u003ccode\u003envm install latest\u003c/code\u003e to install latest version if SemaphoreCI does not provide it from the drop-down\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003c/li\u003e\n\u003cli\u003eSetup: \u003ccode\u003enpm install\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eJob 1: \u003ccode\u003enpm run test-coverage\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eAfter job: \u003ccode\u003enpm run coverage\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eGo to \u003ca href=\"https://codecov.io/gh\" rel=\"nofollow\"\u003eCodecov\u003c/a\u003e and sign up for a free account\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eAdd your project on Codecov and copy to your clipboard the token\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eGo to SemaphoreCI's Project Settings for your project and add \u003ccode\u003eCODECOV_TOKEN\u003c/code\u003e as an environment variable (with the contents from your clipboard)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eRun a test build (\"Rebuild last revision\") on SemaphoreCI and check to make sure your code coverage report uploads properly on Codecov\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eEnsure your \u003ccode\u003eREADME.md\u003c/code\u003e file has the build status and code coverage badges rendered properly (you will need to use a different badge link from each provider if your GitHub repository is private)\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch4 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eAmazon S3 and CloudFront Asset Setup\u003c/h4\u003e\u003ca id=\"user-content-amazon-s3-and-cloudfront-asset-setup\" class=\"anchor\" aria-label=\"Permalink: Amazon S3 and CloudFront Asset Setup\" href=\"#amazon-s3-and-cloudfront-asset-setup\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eIn order for your assets to get properly served in a production environment, you'll need to configure AWS:\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eGo to \u003ca href=\"https://console.aws.amazon.com/iam/home#security_credential\" rel=\"nofollow\"\u003ehttps://console.aws.amazon.com/iam/home#security_credential\u003c/a\u003e ‐ Access Keys – Create New Access Key\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eCopy and paste the newly created key pair for respective properties in your \u003ccode\u003e.env\u003c/code\u003e file (example below)\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-diff notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"-AWS_IAM_KEY=\n+AWS_IAM_KEY=AKIAJMH22P6W674YFC7Q\n-AWS_IAM_SECRET=\n+AWS_IAM_SECRET=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\"\u003e\u003cpre\u003e\u003cspan class=\"pl-md\"\u003e\u003cspan class=\"pl-md\"\u003e-\u003c/span\u003eAWS_IAM_KEY=\u003c/span\u003e\n\u003cspan class=\"pl-mi1\"\u003e\u003cspan class=\"pl-mi1\"\u003e+\u003c/span\u003eAWS_IAM_KEY=AKIAJMH22P6W674YFC7Q\u003c/span\u003e\n\u003cspan class=\"pl-md\"\u003e\u003cspan class=\"pl-md\"\u003e-\u003c/span\u003eAWS_IAM_SECRET=\u003c/span\u003e\n\u003cspan class=\"pl-mi1\"\u003e\u003cspan class=\"pl-mi1\"\u003e+\u003c/span\u003eAWS_IAM_SECRET=9MpR1FOXwPEtPlrlU5WbHjnz2KDcKWSUcB+C5CpS\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eEnable your API by clicking on Overview and then clicking the Enable button\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eGo to \u003ca href=\"https://console.aws.amazon.com/s3/home\" rel=\"nofollow\"\u003ehttps://console.aws.amazon.com/s3/home\u003c/a\u003e – Create Bucket\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eCreate a bucket and copy/paste its name for the property in \u003ccode\u003e.env\u003c/code\u003e (example below)\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-diff notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"-AWS_S3_BUCKET=\n+AWS_S3_BUCKET=lad-development\"\u003e\u003cpre\u003e\u003cspan class=\"pl-md\"\u003e\u003cspan class=\"pl-md\"\u003e-\u003c/span\u003eAWS_S3_BUCKET=\u003c/span\u003e\n\u003cspan class=\"pl-mi1\"\u003e\u003cspan class=\"pl-mi1\"\u003e+\u003c/span\u003eAWS_S3_BUCKET=lad-development\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eGo to \u003ca href=\"https://console.aws.amazon.com/cloudfront/home\" rel=\"nofollow\"\u003ehttps://console.aws.amazon.com/cloudfront/home\u003c/a\u003e – Create Distribution – Get Started\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eSet \"Origin Domain Name\" equal to your S3 bucket name (their autocomplete drop-down will help you find it)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eLeave the remaining defaults as is (some fields might be blank, this is OK)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eCopy/paste the newly created Distribution ID and Domain Name for respective properties in your \u003ccode\u003e.env\u003c/code\u003e file (example below)\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-diff notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"-AWS_CF_DI=\n+AWS_CF_DI=E2IBEULE9QOPVE\n-AWS_CF_DOMAIN=\n+AWS_CF_DOMAIN=d36aditw73gdrz.cloudfront.net\"\u003e\u003cpre\u003e\u003cspan class=\"pl-md\"\u003e\u003cspan class=\"pl-md\"\u003e-\u003c/span\u003eAWS_CF_DI=\u003c/span\u003e\n\u003cspan class=\"pl-mi1\"\u003e\u003cspan class=\"pl-mi1\"\u003e+\u003c/span\u003eAWS_CF_DI=E2IBEULE9QOPVE\u003c/span\u003e\n\u003cspan class=\"pl-md\"\u003e\u003cspan class=\"pl-md\"\u003e-\u003c/span\u003eAWS_CF_DOMAIN=\u003c/span\u003e\n\u003cspan class=\"pl-mi1\"\u003e\u003cspan class=\"pl-mi1\"\u003e+\u003c/span\u003eAWS_CF_DOMAIN=d36aditw73gdrz.cloudfront.net\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTutorials\u003c/h3\u003e\u003ca id=\"user-content-tutorials\" class=\"anchor\" aria-label=\"Permalink: Tutorials\" href=\"#tutorials\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/koajs/koa#getting-started\"\u003eWriting Your App\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://niftylettuce.com/posts/automated-node-app-ci-graceful-zerodowntime-github-pm2/\" rel=\"nofollow\"\u003eContinous Integration and Deployment\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCommunity\u003c/h3\u003e\u003ca id=\"user-content-community\" class=\"anchor\" aria-label=\"Permalink: Community\" href=\"#community\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ca href=\"https://twitter.com/niftylettuce\" rel=\"nofollow\"\u003eFollow us on Twitter\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://join.slack.com/t/ladjs/shared_invite/zt-fqei6z11-Bq2trhwHQxVc5x~ifiZG0g/\" rel=\"nofollow\"\u003eJoin our Slack channel\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.twitch.tv/niftylettuce\" rel=\"nofollow\"\u003eSubscribe to our Twitch channel\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/koajs/koa#community\"\u003eVisit Koa's Community section\u003c/a\u003e.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://slack.mongoosejs.io/\" rel=\"nofollow\"\u003eJoin Mongoose's Slack channel\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eArchitecture\u003c/h2\u003e\u003ca id=\"user-content-architecture\" class=\"anchor\" aria-label=\"Permalink: Architecture\" href=\"#architecture\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe following bash output is the directory structure and organization of Lad:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"tree template -I \u0026quot;build|node_modules|coverage|test\u0026quot;\"\u003e\u003cpre\u003etree template -I \u003cspan class=\"pl-s\"\u003e\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003ebuild|node_modules|coverage|test\u003cspan class=\"pl-pds\"\u003e\"\u003c/span\u003e\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"template\n├── LICENSE\n├── README\n├── ansible\n│   ├── playbooks\n│   │   ├── aws-credentials.yml\n│   │   ├── bree.yml\n│   │   ├── certificates.yml\n│   │   ├── deployment-keys.yml\n│   │   ├── ecosystem.yml\n│   │   ├── env.yml\n│   │   ├── gapp-creds.yml\n│   │   ├── http.yml\n│   │   ├── mongo.yml\n│   │   ├── node.yml\n│   │   ├── python.yml\n│   │   ├── redis.yml\n│   │   ├── security.yml\n│   │   ├── ssh-keys.yml\n│   │   └── templates\n│   │   ├── aws-credentials.j2\n│   │   ├── before.rules.j2\n│   │   ├── ecosystem-api.json.j2\n│   │   ├── ecosystem-bree.json.j2\n│   │   ├── ecosystem-web.json.j2\n│   │   ├── env\n│   │   ├── hosts.yml\n│   │   └── security-limits.d-mongod.conf\n│   └── requirements.yml\n├── ansible-playbook.js\n├── ansible.cfg\n├── api.js\n├── app\n│   ├── controllers\n│   │   ├── api\n│   │   │   ├── index.js\n│   │   │   └── v1\n│   │   │   ├── index.js\n│   │   │   ├── log.js\n│   │   │   └── users.js\n│   │   ├── index.js\n│   │   └── web\n│   │   ├── admin\n│   │   │   ├── index.js\n│   │   │   └── users.js\n│   │   ├── auth.js\n│   │   ├── index.js\n│   │   ├── my-account.js\n│   │   ├── otp\n│   │   │   ├── disable.js\n│   │   │   ├── index.js\n│   │   │   ├── keys.js\n│   │   │   ├── recovery.js\n│   │   │   └── setup.js\n│   │   ├── report.js\n│   │   └── support.js\n│   ├── models\n│   │   ├── index.js\n│   │   ├── inquiry.js\n│   │   └── user.js\n│   └── views\n│   ├── 404.pug\n│   ├── 500.pug\n│   ├── _breadcrumbs.pug\n│   ├── _footer.pug\n│   ├── _nav.pug\n│   ├── _pagination.pug\n│   ├── _register-or-login.pug\n│   ├── about.pug\n│   ├── admin\n│   │   ├── index.pug\n│   │   └── users\n│   │   ├── index.pug\n│   │   └── retrieve.pug\n│   ├── change-email.pug\n│   ├── dashboard\n│   │   └── index.pug\n│   ├── donate.pug\n│   ├── forgot-password.pug\n│   ├── home.pug\n│   ├── layout.pug\n│   ├── my-account\n│   │   ├── index.pug\n│   │   ├── profile.pug\n│   │   └── security.pug\n│   ├── otp\n│   │   ├── enable.pug\n│   │   ├── keys.pug\n│   │   ├── login.pug\n│   │   └── setup.pug\n│   ├── privacy.pug\n│   ├── register-or-login.pug\n│   ├── reset-password.pug\n│   ├── spinner\n│   │   ├── 1.pug\n│   │   ├── 10.pug\n│   │   ├── 11.pug\n│   │   ├── 2.pug\n│   │   ├── 3.pug\n│   │   ├── 4.pug\n│   │   ├── 5.pug\n│   │   ├── 6.pug\n│   │   ├── 7.pug\n│   │   ├── 8.pug\n│   │   ├── 9.pug\n│   │   └── spinner.pug\n│   ├── support.pug\n│   ├── terms.pug\n│   └── verify.pug\n├── assets\n│   ├── browserconfig.xml\n│   ├── css\n│   │   ├── _btn-auth.scss\n│   │   ├── _custom.scss\n│   │   ├── _email.scss\n│   │   ├── _markdown.scss\n│   │   ├── _responsive-backgrounds.scss\n│   │   ├── _responsive-borders.scss\n│   │   ├── _responsive-rounded.scss\n│   │   ├── _swal2.scss\n│   │   ├── _variables.scss\n│   │   └── app.scss\n│   ├── fonts\n│   ├── img\n│   │   ├── android-chrome-192x192.png\n│   │   ├── android-chrome-384x384.png\n│   │   ├── apple-touch-icon.png\n│   │   ├── favicon-16x16.png\n│   │   ├── favicon-32x32.png\n│   │   ├── favicon.ico\n│   │   ├── github-logo.svg\n│   │   ├── google-logo.svg\n│   │   ├── logo-square.svg\n│   │   ├── mstile-150x150.png\n│   │   ├── social.png\n│   │   └── twitter.png\n│   ├── js\n│   │   ├── core.js\n│   │   ├── logger.js\n│   │   └── uncaught.js\n│   ├── robots.txt\n│   └── site.webmanifest\n├── bree.js\n├── config\n│   ├── api.js\n│   ├── bree.js\n│   ├── cookies.js\n│   ├── env.js\n│   ├── filters.js\n│   ├── i18n.js\n│   ├── index.js\n│   ├── koa-cash.js\n│   ├── locales.js\n│   ├── logger.js\n│   ├── meta.js\n│   ├── phrases.js\n│   ├── utilities.js\n│   └── web.js\n├── emails\n│   ├── _content.pug\n│   ├── _footer.pug\n│   ├── _nav.pug\n│   ├── account-update\n│   │   ├── html.pug\n│   │   └── subject.pug\n│   ├── change-email\n│   │   ├── html.pug\n│   │   └── subject.pug\n│   ├── inquiry\n│   │   ├── html.pug\n│   │   └── subject.pug\n│   ├── layout.pug\n│   ├── recovery\n│   │   ├── html.pug\n│   │   └── subject.pug\n│   ├── reset-password\n│   │   ├── html.pug\n│   │   └── subject.pug\n│   ├── two-factor-reminder\n│   │   ├── html.pug\n│   │   └── subject.pug\n│   ├── verify\n│   │   ├── html.pug\n│   │   └── subject.pug\n│   └── welcome\n│   ├── html.pug\n│   └── subject.pug\n├── env\n├── gitignore\n├── gulpfile.js\n├── helpers\n│   ├── email.js\n│   ├── get-email-locals.js\n│   ├── i18n.js\n│   ├── logger.js\n│   ├── markdown.js\n│   ├── passport.js\n│   ├── policies.js\n│   ├── send-verification-email.js\n│   └── to-object.js\n├── index.js\n├── jobs\n│   ├── account-updates.js\n│   ├── index.js\n│   ├── translate-markdown.js\n│   ├── translate-phrases.js\n│   ├── two-factor-reminder.js\n│   └── welcome-email.js\n├── lad.sh\n├── locales\n│   ├── ar.json\n│   ├── cs.json\n│   ├── da.json\n│   ├── de.json\n│   ├── en.json\n│   ├── es.json\n│   ├── fi.json\n│   ├── fr.json\n│   ├── he.json\n│   ├── hu.json\n│   ├── id.json\n│   ├── it.json\n│   ├── ja.json\n│   ├── ko.json\n│   ├── nl.json\n│   ├── no.json\n│   ├── pl.json\n│   ├── pt.json\n│   ├── ru.json\n│   ├── sv.json\n│   ├── th.json\n│   ├── tr.json\n│   ├── uk.json\n│   ├── vi.json\n│   └── zh.json\n├── nodemon.json\n├── package-scripts.js\n├── package.json\n├── proxy.js\n├── routes\n│   ├── api\n│   │   ├── index.js\n│   │   └── v1\n│   │   └── index.js\n│   ├── index.js\n│   └── web\n│   ├── admin.js\n│   ├── auth.js\n│   ├── index.js\n│   ├── my-account.js\n│   └── otp.js\n├── template\n├── web.js\n├── yarn-error.log\n└── yarn.lock\n\n42 directories, 212 files\"\u003e\u003cpre\u003etemplate\n├── LICENSE\n├── README\n├── ansible\n│   ├── playbooks\n│   │   ├── aws-credentials.yml\n│   │   ├── bree.yml\n│   │   ├── certificates.yml\n│   │   ├── deployment-keys.yml\n│   │   ├── ecosystem.yml\n│   │   ├── env.yml\n│   │   ├── gapp-creds.yml\n│   │   ├── http.yml\n│   │   ├── mongo.yml\n│   │   ├── node.yml\n│   │   ├── python.yml\n│   │   ├── redis.yml\n│   │   ├── security.yml\n│   │   ├── ssh-keys.yml\n│   │   └── templates\n│   │   ├── aws-credentials.j2\n│   │   ├── before.rules.j2\n│   │   ├── ecosystem-api.json.j2\n│   │   ├── ecosystem-bree.json.j2\n│   │   ├── ecosystem-web.json.j2\n│   │   ├── env\n│   │   ├── hosts.yml\n│   │   └── security-limits.d-mongod.conf\n│   └── requirements.yml\n├── ansible-playbook.js\n├── ansible.cfg\n├── api.js\n├── app\n│   ├── controllers\n│   │   ├── api\n│   │   │   ├── index.js\n│   │   │   └── v1\n│   │   │   ├── index.js\n│   │   │   ├── log.js\n│   │   │   └── users.js\n│   │   ├── index.js\n│   │   └── web\n│   │   ├── admin\n│   │   │   ├── index.js\n│   │   │   └── users.js\n│   │   ├── auth.js\n│   │   ├── index.js\n│   │   ├── my-account.js\n│   │   ├── otp\n│   │   │   ├── disable.js\n│   │   │   ├── index.js\n│   │   │   ├── keys.js\n│   │   │   ├── recovery.js\n│   │   │   └── setup.js\n│   │   ├── report.js\n│   │   └── support.js\n│   ├── models\n│   │   ├── index.js\n│   │   ├── inquiry.js\n│   │   └── user.js\n│   └── views\n│   ├── 404.pug\n│   ├── 500.pug\n│   ├── _breadcrumbs.pug\n│   ├── _footer.pug\n│   ├── _nav.pug\n│   ├── _pagination.pug\n│   ├── _register-or-login.pug\n│   ├── about.pug\n│   ├── admin\n│   │   ├── index.pug\n│   │   └── users\n│   │   ├── index.pug\n│   │   └── retrieve.pug\n│   ├── change-email.pug\n│   ├── dashboard\n│   │   └── index.pug\n│   ├── donate.pug\n│   ├── forgot-password.pug\n│   ├── home.pug\n│   ├── layout.pug\n│   ├── my-account\n│   │   ├── index.pug\n│   │   ├── profile.pug\n│   │   └── security.pug\n│   ├── otp\n│   │   ├── enable.pug\n│   │   ├── keys.pug\n│   │   ├── login.pug\n│   │   └── setup.pug\n│   ├── privacy.pug\n│   ├── register-or-login.pug\n│   ├── reset-password.pug\n│   ├── spinner\n│   │   ├── 1.pug\n│   │   ├── 10.pug\n│   │   ├── 11.pug\n│   │   ├── 2.pug\n│   │   ├── 3.pug\n│   │   ├── 4.pug\n│   │   ├── 5.pug\n│   │   ├── 6.pug\n│   │   ├── 7.pug\n│   │   ├── 8.pug\n│   │   ├── 9.pug\n│   │   └── spinner.pug\n│   ├── support.pug\n│   ├── terms.pug\n│   └── verify.pug\n├── assets\n│   ├── browserconfig.xml\n│   ├── css\n│   │   ├── _btn-auth.scss\n│   │   ├── _custom.scss\n│   │   ├── _email.scss\n│   │   ├── _markdown.scss\n│   │   ├── _responsive-backgrounds.scss\n│   │   ├── _responsive-borders.scss\n│   │   ├── _responsive-rounded.scss\n│   │   ├── _swal2.scss\n│   │   ├── _variables.scss\n│   │   └── app.scss\n│   ├── fonts\n│   ├── img\n│   │   ├── android-chrome-192x192.png\n│   │   ├── android-chrome-384x384.png\n│   │   ├── apple-touch-icon.png\n│   │   ├── favicon-16x16.png\n│   │   ├── favicon-32x32.png\n│   │   ├── favicon.ico\n│   │   ├── github-logo.svg\n│   │   ├── google-logo.svg\n│   │   ├── logo-square.svg\n│   │   ├── mstile-150x150.png\n│   │   ├── social.png\n│   │   └── twitter.png\n│   ├── js\n│   │   ├── core.js\n│   │   ├── logger.js\n│   │   └── uncaught.js\n│   ├── robots.txt\n│   └── site.webmanifest\n├── bree.js\n├── config\n│   ├── api.js\n│   ├── bree.js\n│   ├── cookies.js\n│   ├── env.js\n│   ├── filters.js\n│   ├── i18n.js\n│   ├── index.js\n│   ├── koa-cash.js\n│   ├── locales.js\n│   ├── logger.js\n│   ├── meta.js\n│   ├── phrases.js\n│   ├── utilities.js\n│   └── web.js\n├── emails\n│   ├── _content.pug\n│   ├── _footer.pug\n│   ├── _nav.pug\n│   ├── account-update\n│   │   ├── html.pug\n│   │   └── subject.pug\n│   ├── change-email\n│   │   ├── html.pug\n│   │   └── subject.pug\n│   ├── inquiry\n│   │   ├── html.pug\n│   │   └── subject.pug\n│   ├── layout.pug\n│   ├── recovery\n│   │   ├── html.pug\n│   │   └── subject.pug\n│   ├── reset-password\n│   │   ├── html.pug\n│   │   └── subject.pug\n│   ├── two-factor-reminder\n│   │   ├── html.pug\n│   │   └── subject.pug\n│   ├── verify\n│   │   ├── html.pug\n│   │   └── subject.pug\n│   └── welcome\n│   ├── html.pug\n│   └── subject.pug\n├── env\n├── gitignore\n├── gulpfile.js\n├── helpers\n│   ├── email.js\n│   ├── get-email-locals.js\n│   ├── i18n.js\n│   ├── logger.js\n│   ├── markdown.js\n│   ├── passport.js\n│   ├── policies.js\n│   ├── send-verification-email.js\n│   └── to-object.js\n├── index.js\n├── \u003cspan class=\"pl-c1\"\u003ejobs\u003c/span\u003e\n│   ├── account-updates.js\n│   ├── index.js\n│   ├── translate-markdown.js\n│   ├── translate-phrases.js\n│   ├── two-factor-reminder.js\n│   └── welcome-email.js\n├── lad.sh\n├── locales\n│   ├── ar.json\n│   ├── cs.json\n│   ├── da.json\n│   ├── de.json\n│   ├── en.json\n│   ├── es.json\n│   ├── fi.json\n│   ├── fr.json\n│   ├── he.json\n│   ├── hu.json\n│   ├── id.json\n│   ├── it.json\n│   ├── ja.json\n│   ├── ko.json\n│   ├── nl.json\n│   ├── no.json\n│   ├── pl.json\n│   ├── pt.json\n│   ├── ru.json\n│   ├── sv.json\n│   ├── th.json\n│   ├── tr.json\n│   ├── uk.json\n│   ├── vi.json\n│   └── zh.json\n├── nodemon.json\n├── package-scripts.js\n├── package.json\n├── proxy.js\n├── routes\n│   ├── api\n│   │   ├── index.js\n│   │   └── v1\n│   │   └── index.js\n│   ├── index.js\n│   └── web\n│   ├── admin.js\n│   ├── auth.js\n│   ├── index.js\n│   ├── my-account.js\n│   └── otp.js\n├── template\n├── web.js\n├── yarn-error.log\n└── yarn.lock\n\n42 directories, 212 files\u003c/pre\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003ePrinciples\u003c/h2\u003e\u003ca id=\"user-content-principles\" class=\"anchor\" aria-label=\"Permalink: Principles\" href=\"#principles\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eLad is designed according to these principles:\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003eAlways be developer-friendly\u003c/li\u003e\n\u003cli\u003eAdhere to \u003ca href=\"https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller\" rel=\"nofollow\"\u003eMVC\u003c/a\u003e, \u003ca href=\"https://en.wikipedia.org/wiki/Unix_philosophy\" rel=\"nofollow\"\u003eUnix\u003c/a\u003e, \u003ca href=\"https://en.wikipedia.org/wiki/KISS_principle\" rel=\"nofollow\"\u003eKISS\u003c/a\u003e, \u003ca href=\"https://en.wikipedia.org/wiki/Don%27t_repeat_yourself\" rel=\"nofollow\"\u003eDRY\u003c/a\u003e, \u003ca href=\"https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it\" rel=\"nofollow\"\u003eYAGNI\u003c/a\u003e, \u003ca href=\"https://12factor.net/\" rel=\"nofollow\"\u003eTwelve Factor\u003c/a\u003e, \u003ca href=\"https://en.wikipedia.org/wiki/Occam%27s_razor\" rel=\"nofollow\"\u003eOccam's razor\u003c/a\u003e, and \u003ca href=\"https://en.wikipedia.org/wiki/Eating_your_own_dog_food\" rel=\"nofollow\"\u003edogfooding\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eTarget the scrappy, bootstrapped, and \u003ca href=\"http://www.paulgraham.com/ramenprofitable.html\" rel=\"nofollow\"\u003eramen-profitable\u003c/a\u003e hacker\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eRelated\u003c/h2\u003e\u003ca id=\"user-content-related\" class=\"anchor\" aria-label=\"Permalink: Related\" href=\"#related\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003ca href=\"https://lipo.io\" rel=\"nofollow\"\u003elipo\u003c/a\u003e - Free image manipulation API service built on top of \u003ca href=\"http://sharp.dimens.io/\" rel=\"nofollow\"\u003eSharp\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://cabinjs.com\" rel=\"nofollow\"\u003ecabin\u003c/a\u003e - Logging and analytics solution for \u003ca href=\"https://nodejs.org\" rel=\"nofollow\"\u003eNode.js\u003c/a\u003e, \u003ca href=\"https://lad.js.org\" rel=\"nofollow\"\u003eLad\u003c/a\u003e, \u003ca href=\"http://koajs.com/\" rel=\"nofollow\"\u003eKoa\u003c/a\u003e, and \u003ca href=\"https://expressjs.com\" rel=\"nofollow\"\u003eExpress\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://lass.js.org\" rel=\"nofollow\"\u003elass\u003c/a\u003e - Scaffold a modern boilerplate for \u003ca href=\"https://nodejs.org\" rel=\"nofollow\"\u003eNode.js\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eContributing\u003c/h2\u003e\u003ca id=\"user-content-contributing\" class=\"anchor\" aria-label=\"Permalink: Contributing\" href=\"#contributing\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eInteresting in contributing to this project or testing early releases?\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eFollow all of the above \u003ca href=\"#requirements\"\u003eRequirements\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eYou will need to fork and clone this repository locally\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp dir=\"auto\"\u003eAfter forking, follow these steps:\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"cd lad\nyarn install\ncd template\nyarn install\nyarn start\"\u003e\u003cpre\u003e\u003cspan class=\"pl-c1\"\u003ecd\u003c/span\u003e lad\nyarn install\n\u003cspan class=\"pl-c1\"\u003ecd\u003c/span\u003e template\nyarn install\nyarn start\u003c/pre\u003e\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp dir=\"auto\"\u003eIf you'd like to preview changes to the \u003ccode\u003eREADME.md\u003c/code\u003e file, you can use \u003ccode\u003edocute\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"yarn global add docute-cli\ncd lad\ndocute ./\"\u003e\u003cpre\u003eyarn global add docute-cli\n\u003cspan class=\"pl-c1\"\u003ecd\u003c/span\u003e lad\ndocute ./\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThen visit \u003ca href=\"http://localhost:8080\" rel=\"nofollow\"\u003ehttp://localhost:8080\u003c/a\u003e in your browser.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eContributors\u003c/h2\u003e\u003ca id=\"user-content-contributors\" class=\"anchor\" aria-label=\"Permalink: Contributors\" href=\"#contributors\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cmarkdown-accessiblity-table\u003e\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eName\u003c/th\u003e\n\u003cth\u003eWebsite\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cstrong\u003eNick Baugh\u003c/strong\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ca href=\"http://niftylettuce.com\" rel=\"nofollow\"\u003ehttp://niftylettuce.com\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cstrong\u003eShaun Warman\u003c/strong\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ca href=\"https://shaunwarman.com/\" rel=\"nofollow\"\u003ehttps://shaunwarman.com/\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\u003c/markdown-accessiblity-table\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTrademark Notice\u003c/h2\u003e\u003ca id=\"user-content-trademark-notice\" class=\"anchor\" aria-label=\"Permalink: Trademark Notice\" href=\"#trademark-notice\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eLad, Lass, Cabin, Lipo, and their respective logos are trademarks of Niftylettuce LLC.\nThese trademarks may not be reproduced, distributed, transmitted, or otherwise used, except with the prior written permission of Niftylettuce LLC.\nIf you are seeking permission to use these trademarks, then please \u003ca href=\"mailto:niftylettuce@gmail.com\"\u003econtact us\u003c/a\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eLicense\u003c/h2\u003e\u003ca id=\"user-content-license\" class=\"anchor\" aria-label=\"Permalink: License\" href=\"#license\"\u003e\u003csvg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/LICENSE\"\u003eMIT\u003c/a\u003e © \u003ca href=\"http://niftylettuce.com\" rel=\"nofollow\"\u003eNick Baugh\u003c/a\u003e\u003c/p\u003e\n\u003ch2 dir=\"auto\"\u003e\u003c/h2\u003e\n\u003cp dir=\"auto\"\u003e\u003ca href=\"#\"\u003e\u003cimg src=\"/ladjs/lad/raw/snyk-fix-bed97d0c625fc25446b4c14528f312d1/media/lad-footer.png\" alt=\"#\" style=\"max-width: 100%;\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003c/article\u003e","loaded":true,"timedOut":false,"errorMessage":null,"headerInfo":{"toc":[{"level":1,"text":"","anchor":"--","htmlText":""},{"level":3,"text":"Project Spotlight: Forward Email @ https://forwardemail.net (made with Lad)","anchor":"project-spotlight-forward-email--httpsforwardemailnet-made-with-lad","htmlText":"Project Spotlight: Forward Email @ https://forwardemail.net (made with Lad)"},{"level":4,"text":"Live Framework Demo:https://lad.sh","anchor":"live-framework-demo-httpsladsh","htmlText":"Live Framework Demo:https://lad.sh"},{"level":2,"text":"Table of Contents","anchor":"table-of-contents","htmlText":"Table of Contents"},{"level":2,"text":"Features","anchor":"features","htmlText":"Features"},{"level":3,"text":"Microservices","anchor":"microservices","htmlText":"Microservices"},{"level":3,"text":"Front-end","anchor":"front-end","htmlText":"Front-end"},{"level":3,"text":"Back-end","anchor":"back-end","htmlText":"Back-end"},{"level":3,"text":"Translation","anchor":"translation","htmlText":"Translation"},{"level":3,"text":"Email Engine","anchor":"email-engine","htmlText":"Email Engine"},{"level":3,"text":"Error Handling","anchor":"error-handling","htmlText":"Error Handling"},{"level":3,"text":"Performance","anchor":"performance","htmlText":"Performance"},{"level":3,"text":"Security","anchor":"security","htmlText":"Security"},{"level":2,"text":"Get Started","anchor":"get-started","htmlText":"Get Started"},{"level":3,"text":"Requirements","anchor":"requirements","htmlText":"Requirements"},{"level":3,"text":"Install","anchor":"install","htmlText":"Install"},{"level":3,"text":"Usage","anchor":"usage","htmlText":"Usage"},{"level":4,"text":"Create a project","anchor":"create-a-project","htmlText":"Create a project"},{"level":4,"text":"Development","anchor":"development","htmlText":"Development"},{"level":5,"text":"Debugging","anchor":"debugging","htmlText":"Debugging"},{"level":4,"text":"Production","anchor":"production","htmlText":"Production"},{"level":4,"text":"Provisioning","anchor":"provisioning","htmlText":"Provisioning"},{"level":5,"text":"Deployment","anchor":"deployment","htmlText":"Deployment"},{"level":4,"text":"Tests","anchor":"tests","htmlText":"Tests"},{"level":3,"text":"Configuration","anchor":"configuration","htmlText":"Configuration"},{"level":4,"text":"Environment Variables","anchor":"environment-variables","htmlText":"Environment Variables"},{"level":4,"text":"SSL Configuration","anchor":"ssl-configuration","htmlText":"SSL Configuration"},{"level":4,"text":"Outbound Email Configuration","anchor":"outbound-email-configuration","htmlText":"Outbound Email Configuration"},{"level":4,"text":"Favicon and Touch Icon Configuration","anchor":"favicon-and-touch-icon-configuration","htmlText":"Favicon and Touch Icon Configuration"},{"level":4,"text":"Authentication Methods","anchor":"authentication-methods","htmlText":"Authentication Methods"},{"level":5,"text":"Google Auth","anchor":"google-auth","htmlText":"Google Auth"},{"level":4,"text":"Translation Configuration","anchor":"translation-configuration","htmlText":"Translation Configuration"},{"level":4,"text":"Continuous Integration and Code Coverage","anchor":"continuous-integration-and-code-coverage","htmlText":"Continuous Integration and Code Coverage"},{"level":4,"text":"Amazon S3 and CloudFront Asset Setup","anchor":"amazon-s3-and-cloudfront-asset-setup","htmlText":"Amazon S3 and CloudFront Asset Setup"},{"level":3,"text":"Tutorials","anchor":"tutorials","htmlText":"Tutorials"},{"level":3,"text":"Community","anchor":"community","htmlText":"Community"},{"level":2,"text":"Architecture","anchor":"architecture","htmlText":"Architecture"},{"level":2,"text":"Principles","anchor":"principles","htmlText":"Principles"},{"level":2,"text":"Related","anchor":"related","htmlText":"Related"},{"level":2,"text":"Contributing","anchor":"contributing","htmlText":"Contributing"},{"level":2,"text":"Contributors","anchor":"contributors","htmlText":"Contributors"},{"level":2,"text":"Trademark Notice","anchor":"trademark-notice","htmlText":"Trademark Notice"},{"level":2,"text":"License","anchor":"license","htmlText":"License"}],"siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fladjs%2Flad%2Ftree%2Fsnyk-fix-bed97d0c625fc25446b4c14528f312d1"}},{"displayName":"CODE_OF_CONDUCT.md","repoName":".github","refName":"main","path":"CODE_OF_CONDUCT.md","preferredFileType":"code_of_conduct","tabName":"Code of conduct","richText":null,"loaded":false,"timedOut":false,"errorMessage":null,"headerInfo":{"toc":null,"siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fladjs%2Flad%2Ftree%2Fsnyk-fix-bed97d0c625fc25446b4c14528f312d1"}},{"displayName":"LICENSE","repoName":"lad","refName":"snyk-fix-bed97d0c625fc25446b4c14528f312d1","path":"LICENSE","preferredFileType":"license","tabName":"License","richText":null,"loaded":false,"timedOut":false,"errorMessage":null,"headerInfo":{"toc":null,"siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fladjs%2Flad%2Ftree%2Fsnyk-fix-bed97d0c625fc25446b4c14528f312d1"}},{"displayName":"SECURITY.md","repoName":".github","refName":"main","path":"SECURITY.md","preferredFileType":"security","tabName":"Security","richText":null,"loaded":false,"timedOut":false,"errorMessage":null,"headerInfo":{"toc":null,"siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fladjs%2Flad%2Ftree%2Fsnyk-fix-bed97d0c625fc25446b4c14528f312d1"}}],"overviewFilesProcessingTime":0}},"appPayload":{"helpUrl":"https://docs.github.com","findFileWorkerPath":"/assets-cdn/worker/find-file-worker-7d7eb7c71814.js","findInFileWorkerPath":"/assets-cdn/worker/find-in-file-worker-96e76d5fdb2c.js","githubDevUrl":null,"enabled_features":{"copilot_workspace":null,"code_nav_ui_events":false,"overview_shared_code_dropdown_button":false,"react_blob_overlay":false,"accessible_code_button":true,"github_models_repo_integration":false}}}}</script> <div data-target="react-partial.reactRoot"><style data-styled="true" data-styled-version="5.3.11">.iVEunk{margin-top:16px;margin-bottom:16px;}/*!sc*/ .jzuOtQ{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;}/*!sc*/ .bGojzy{margin-bottom:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;row-gap:16px;}/*!sc*/ .iNSVHo{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;padding-bottom:16px;padding-top:8px;}/*!sc*/ .bVgnfw{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;gap:8px;}/*!sc*/ @media screen and (max-width:320px){.bVgnfw{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}}/*!sc*/ .CEgMp{position:relative;}/*!sc*/ @media screen and (max-width:380px){.CEgMp .ref-selector-button-text-container{max-width:80px;}}/*!sc*/ @media screen and (max-width:320px){.CEgMp{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}.CEgMp .overview-ref-selector{width:100%;}.CEgMp .overview-ref-selector > span{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:start;-webkit-justify-content:flex-start;-ms-flex-pack:start;justify-content:flex-start;}.CEgMp .overview-ref-selector > span > span[data-component="text"]{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}}/*!sc*/ .gMOVLe[data-size="medium"]{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-width:0;}/*!sc*/ .gMOVLe[data-size="medium"] svg{color:var(--fgColor-muted,var(--color-fg-muted,#656d76));}/*!sc*/ .gMOVLe[data-size="medium"] > span{width:inherit;}/*!sc*/ .gUkoLg{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}/*!sc*/ .bZBlpz{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;}/*!sc*/ .lhTYNA{margin-right:4px;color:var(--fgColor-muted,var(--color-fg-muted,#656d76));}/*!sc*/ .ffLUq{font-size:14px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}/*!sc*/ .bmcJak{min-width:0;}/*!sc*/ .fLXEGX{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}/*!sc*/ @media screen and (max-width:1079px){.fLXEGX{display:none;}}/*!sc*/ .lmSMZJ[data-size="medium"]{color:var(--fgColor-muted,var(--color-fg-muted,#656d76));padding-left:4px;padding-right:4px;}/*!sc*/ .lmSMZJ[data-size="medium"] span[data-component="leadingVisual"]{margin-right:4px !important;}/*!sc*/ .dqfxud{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}/*!sc*/ @media screen and (min-width:1080px){.dqfxud{display:none;}}/*!sc*/ @media screen and (max-width:543px){.dqfxud{display:none;}}/*!sc*/ .fGwBZA[data-size="medium"][data-no-visuals]{color:var(--fgColor-muted,var(--color-fg-muted,#656d76));}/*!sc*/ .jxTzTd{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding-left:8px;gap:8px;}/*!sc*/ .gqqBXN{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;gap:8px;}/*!sc*/ @media screen and (max-width:543px){.gqqBXN{display:none;}}/*!sc*/ .dzXgxt{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}/*!sc*/ @media screen and (max-width:1011px){.dzXgxt{display:none;}}/*!sc*/ .iWFGlI{margin-left:8px;margin-right:8px;margin:0;}/*!sc*/ .vcvyP{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;min-width:160px;}/*!sc*/ .YUPas{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}/*!sc*/ @media screen and (min-width:1012px){.YUPas{display:none;}}/*!sc*/ .izFOf{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}/*!sc*/ @media screen and (min-width:544px){.izFOf{display:none;}}/*!sc*/ .cjVDqW{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;gap:8px;background-color:var(--bgColor-muted,var(--color-canvas-subtle,#f6f8fa));font-size:14px;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;border:solid 1px;border-color:var(--borderColor-default,var(--color-border-default,#d0d7de));border-radius:6px;padding-left:16px;padding-right:8px;padding-top:8px;padding-bottom:8px;margin-bottom:16px;min-height:50px;}/*!sc*/ .vIPPs{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;gap:16px;}/*!sc*/ .fdROMU{width:100%;border-collapse:separate;border-spacing:0;border:1px solid;border-color:var(--borderColor-default,var(--color-border-default,#d0d7de));border-radius:6px;table-layout:fixed;overflow:unset;}/*!sc*/ .jGKpsv{height:0px;line-height:0px;}/*!sc*/ .jGKpsv tr{height:0px;font-size:0px;}/*!sc*/ .jdgHnn{padding:16px;color:var(--fgColor-muted,var(--color-fg-muted,#656d76));font-size:12px;text-align:left;height:40px;}/*!sc*/ .jdgHnn th{padding-left:16px;background-color:var(--bgColor-muted,var(--color-canvas-subtle,#f6f8fa));}/*!sc*/ .bQivRW{width:100%;border-top-left-radius:6px;}/*!sc*/ @media screen and (min-width:544px){.bQivRW{display:none;}}/*!sc*/ .ldkMIO{width:40%;border-top-left-radius:6px;}/*!sc*/ @media screen and (max-width:543px){.ldkMIO{display:none;}}/*!sc*/ .jMbWeI{text-align:right;padding-right:16px;width:136px;border-top-right-radius:6px;}/*!sc*/ .gpqjiB{color:var(--fgColor-muted,var(--color-fg-muted,#656d76));font-size:12px;height:40px;}/*!sc*/ .dzCJzi{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;gap:8px;min-width:273px;padding:8px;}/*!sc*/ @media screen and (min-width:544px){.dzCJzi{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;}}/*!sc*/ .eNCcrz{text-align:center;vertical-align:center;height:40px;border-top:1px solid;border-color:var(--borderColor-default,var(--color-border-default,#d0d7de));}/*!sc*/ .bHTcCe{border-top:1px solid var(--borderColor-default,var(--color-border-default));cursor:pointer;}/*!sc*/ .csrIcr{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;gap:16px;}/*!sc*/ .bUQNHB{border:1px solid;border-color:var(--borderColor-default,var(--color-border-default,#d0d7de));border-radius:6px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}/*!sc*/ @media screen and (max-width:543px){.bUQNHB{margin-left:-16px;margin-right:-16px;max-width:calc(100% + 32px);}}/*!sc*/ @media screen and (min-width:544px){.bUQNHB{max-width:100%;}}/*!sc*/ .jPdcfu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;border-bottom:1px solid;border-bottom-color:var(--borderColor-default,var(--color-border-default,#d0d7de));-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding-right:8px;position:-webkit-sticky;position:sticky;top:0;background-color:var(--bgColor-default,var(--color-canvas-default,#ffffff));z-index:1;border-top-left-radius:6px;border-top-right-radius:6px;}/*!sc*/ .iphEWz{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;border-bottom:none;max-width:100%;padding-left:8px;padding-right:8px;}/*!sc*/ .hUCRAk{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}/*!sc*/ .cwoBXV[data-size="medium"]{color:var(--fgColor-muted,var(--color-fg-subtle,#6e7781));padding-left:8px;padding-right:8px;}/*!sc*/ .QkQOb{padding:32px;overflow:auto;}/*!sc*/ data-styled.g1[id="Box-sc-g0xbh4-0"]{content:"iVEunk,jzuOtQ,bGojzy,iNSVHo,bVgnfw,CEgMp,gMOVLe,gUkoLg,bZBlpz,lhTYNA,ffLUq,bmcJak,fLXEGX,lmSMZJ,dqfxud,fGwBZA,jxTzTd,gqqBXN,dzXgxt,iWFGlI,vcvyP,YUPas,izFOf,cjVDqW,vIPPs,fdROMU,jGKpsv,jdgHnn,bQivRW,ldkMIO,jMbWeI,gpqjiB,dzCJzi,eNCcrz,bHTcCe,csrIcr,bUQNHB,jPdcfu,iphEWz,hUCRAk,cwoBXV,QkQOb,"}/*!sc*/ .brGdpi{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;-webkit-clip:rect(0,0,0,0);clip:rect(0,0,0,0);white-space:nowrap;border-width:0;}/*!sc*/ data-styled.g5[id="_VisuallyHidden__VisuallyHidden-sc-11jhm7a-0"]{content:"brGdpi,"}/*!sc*/ .hWlpPn{position:relative;display:inline-block;}/*!sc*/ .hWlpPn::after{position:absolute;z-index:1000000;display:none;padding:0.5em 0.75em;font:normal normal 11px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";-webkit-font-smoothing:subpixel-antialiased;color:var(--tooltip-fgColor,var(--fgColor-onEmphasis,var(--color-fg-on-emphasis,#ffffff)));text-align:center;-webkit-text-decoration:none;text-decoration:none;text-shadow:none;text-transform:none;-webkit-letter-spacing:normal;-moz-letter-spacing:normal;-ms-letter-spacing:normal;letter-spacing:normal;word-wrap:break-word;white-space:pre;pointer-events:none;content:attr(aria-label);background:var(--tooltip-bgColor,var(--bgColor-emphasis,var(--color-neutral-emphasis-plus,#24292f)));border-radius:6px;opacity:0;}/*!sc*/ @-webkit-keyframes tooltip-appear{from{opacity:0;}to{opacity:1;}}/*!sc*/ @keyframes tooltip-appear{from{opacity:0;}to{opacity:1;}}/*!sc*/ .hWlpPn:hover::after,.hWlpPn:active::after,.hWlpPn:focus::after,.hWlpPn:focus-within::after{display:inline-block;-webkit-text-decoration:none;text-decoration:none;-webkit-animation-name:tooltip-appear;animation-name:tooltip-appear;-webkit-animation-duration:0.1s;animation-duration:0.1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;-webkit-animation-delay:0s;animation-delay:0s;}/*!sc*/ .hWlpPn.tooltipped-no-delay:hover::after,.hWlpPn.tooltipped-no-delay:active::after,.hWlpPn.tooltipped-no-delay:focus::after,.hWlpPn.tooltipped-no-delay:focus-within::after{-webkit-animation-delay:0s;animation-delay:0s;}/*!sc*/ .hWlpPn.tooltipped-multiline:hover::after,.hWlpPn.tooltipped-multiline:active::after,.hWlpPn.tooltipped-multiline:focus::after,.hWlpPn.tooltipped-multiline:focus-within::after{display:table-cell;}/*!sc*/ .hWlpPn.tooltipped-s::after,.hWlpPn.tooltipped-se::after,.hWlpPn.tooltipped-sw::after{top:100%;right:50%;margin-top:6px;}/*!sc*/ .hWlpPn.tooltipped-se::after{right:auto;left:50%;margin-left:-16px;}/*!sc*/ .hWlpPn.tooltipped-sw::after{margin-right:-16px;}/*!sc*/ .hWlpPn.tooltipped-n::after,.hWlpPn.tooltipped-ne::after,.hWlpPn.tooltipped-nw::after{right:50%;bottom:100%;margin-bottom:6px;}/*!sc*/ .hWlpPn.tooltipped-ne::after{right:auto;left:50%;margin-left:-16px;}/*!sc*/ .hWlpPn.tooltipped-nw::after{margin-right:-16px;}/*!sc*/ .hWlpPn.tooltipped-s::after,.hWlpPn.tooltipped-n::after{-webkit-transform:translateX(50%);-ms-transform:translateX(50%);transform:translateX(50%);}/*!sc*/ .hWlpPn.tooltipped-w::after{right:100%;bottom:50%;margin-right:6px;-webkit-transform:translateY(50%);-ms-transform:translateY(50%);transform:translateY(50%);}/*!sc*/ .hWlpPn.tooltipped-e::after{bottom:50%;left:100%;margin-left:6px;-webkit-transform:translateY(50%);-ms-transform:translateY(50%);transform:translateY(50%);}/*!sc*/ .hWlpPn.tooltipped-multiline::after{width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:250px;word-wrap:break-word;white-space:pre-line;border-collapse:separate;}/*!sc*/ .hWlpPn.tooltipped-multiline.tooltipped-s::after,.hWlpPn.tooltipped-multiline.tooltipped-n::after{right:auto;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);}/*!sc*/ .hWlpPn.tooltipped-multiline.tooltipped-w::after,.hWlpPn.tooltipped-multiline.tooltipped-e::after{right:100%;}/*!sc*/ .hWlpPn.tooltipped-align-right-2::after{right:0;margin-right:0;}/*!sc*/ .hWlpPn.tooltipped-align-left-2::after{left:0;margin-left:0;}/*!sc*/ data-styled.g16[id="Tooltip__TooltipBase-sc-17tf59c-0"]{content:"hWlpPn,"}/*!sc*/ .liVpTx{display:inline-block;overflow:hidden;text-overflow:ellipsis;vertical-align:top;white-space:nowrap;max-width:125px;}/*!sc*/ data-styled.g18[id="Truncate__StyledTruncate-sc-23o1d2-0"]{content:"liVpTx,"}/*!sc*/ </style> <!-- --> <!-- --> <div class="Box-sc-g0xbh4-0 iVEunk"><div class="Box-sc-g0xbh4-0 jzuOtQ"><div class="Box-sc-g0xbh4-0 bGojzy"></div></div><div class="Box-sc-g0xbh4-0 iNSVHo"><div class="Box-sc-g0xbh4-0 bVgnfw"><div class="Box-sc-g0xbh4-0 CEgMp"><button type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-label="snyk-fix-bed97d0c625fc25446b4c14528f312d1 branch" data-testid="anchor-button" class="Box-sc-g0xbh4-0 gMOVLe prc-Button-ButtonBase-c50BI overview-ref-selector width-full" data-loading="false" data-size="medium" data-variant="default" aria-describedby="branch-picker-repos-header-ref-selector-loading-announcement" id="branch-picker-repos-header-ref-selector"><span data-component="buttonContent" class="Box-sc-g0xbh4-0 gUkoLg prc-Button-ButtonContent-HKbr-"><span data-component="text" class="prc-Button-Label-pTQ3x"><div class="Box-sc-g0xbh4-0 bZBlpz"><div class="Box-sc-g0xbh4-0 lhTYNA"><svg aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></div><div class="Box-sc-g0xbh4-0 ffLUq ref-selector-button-text-container"><span class="Box-sc-g0xbh4-0 bmcJak prc-Text-Text-0ima0"> <!-- -->snyk-fix-bed97d0c625fc25446b4c14528f312d1</span></div></div></span><span data-component="trailingVisual" class="prc-Button-Visual-2epfX prc-Button-VisualWrap-Db-eB"><svg aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></span></button><button hidden="" data-hotkey-scope="read-only-cursor-text-area"></button></div><div class="Box-sc-g0xbh4-0 fLXEGX"><a style="--button-color:fg.muted" type="button" href="/ladjs/lad/branches" class="Box-sc-g0xbh4-0 lmSMZJ prc-Button-ButtonBase-c50BI" data-loading="false" data-size="medium" data-variant="invisible" aria-describedby=":Rclab:-loading-announcement"><span data-component="buttonContent" class="Box-sc-g0xbh4-0 gUkoLg prc-Button-ButtonContent-HKbr-"><span data-component="leadingVisual" class="prc-Button-Visual-2epfX prc-Button-VisualWrap-Db-eB"><svg aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></span><span data-component="text" class="prc-Button-Label-pTQ3x">Branches</span></span></a><a style="--button-color:fg.muted" type="button" href="/ladjs/lad/tags" class="Box-sc-g0xbh4-0 lmSMZJ prc-Button-ButtonBase-c50BI" data-loading="false" data-size="medium" data-variant="invisible" aria-describedby=":Rklab:-loading-announcement"><span data-component="buttonContent" class="Box-sc-g0xbh4-0 gUkoLg prc-Button-ButtonContent-HKbr-"><span data-component="leadingVisual" class="prc-Button-Visual-2epfX prc-Button-VisualWrap-Db-eB"><svg aria-hidden="true" focusable="false" class="octicon octicon-tag" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1 7.775V2.75C1 1.784 1.784 1 2.75 1h5.025c.464 0 .91.184 1.238.513l6.25 6.25a1.75 1.75 0 0 1 0 2.474l-5.026 5.026a1.75 1.75 0 0 1-2.474 0l-6.25-6.25A1.752 1.752 0 0 1 1 7.775Zm1.5 0c0 .066.026.13.073.177l6.25 6.25a.25.25 0 0 0 .354 0l5.025-5.025a.25.25 0 0 0 0-.354l-6.25-6.25a.25.25 0 0 0-.177-.073H2.75a.25.25 0 0 0-.25.25ZM6 5a1 1 0 1 1 0 2 1 1 0 0 1 0-2Z"></path></svg></span><span data-component="text" class="prc-Button-Label-pTQ3x">Tags</span></span></a></div><div class="Box-sc-g0xbh4-0 dqfxud"><a style="--button-color:fg.muted" type="button" aria-label="Go to Branches page" href="/ladjs/lad/branches" class="Box-sc-g0xbh4-0 fGwBZA prc-Button-ButtonBase-c50BI" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="invisible" aria-describedby=":Relab:-loading-announcement"><svg aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></a><a style="--button-color:fg.muted" type="button" aria-label="Go to Tags page" href="/ladjs/lad/tags" class="Box-sc-g0xbh4-0 fGwBZA prc-Button-ButtonBase-c50BI" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="invisible" aria-describedby=":Rmlab:-loading-announcement"><svg aria-hidden="true" focusable="false" class="octicon octicon-tag" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1 7.775V2.75C1 1.784 1.784 1 2.75 1h5.025c.464 0 .91.184 1.238.513l6.25 6.25a1.75 1.75 0 0 1 0 2.474l-5.026 5.026a1.75 1.75 0 0 1-2.474 0l-6.25-6.25A1.752 1.752 0 0 1 1 7.775Zm1.5 0c0 .066.026.13.073.177l6.25 6.25a.25.25 0 0 0 .354 0l5.025-5.025a.25.25 0 0 0 0-.354l-6.25-6.25a.25.25 0 0 0-.177-.073H2.75a.25.25 0 0 0-.25.25ZM6 5a1 1 0 1 1 0 2 1 1 0 0 1 0-2Z"></path></svg></a></div></div><div class="Box-sc-g0xbh4-0 jxTzTd"><div class="Box-sc-g0xbh4-0 gqqBXN"><div class="Box-sc-g0xbh4-0 dzXgxt"><!--$--><div class="Box-sc-g0xbh4-0 iWFGlI"><span class="Box-sc-g0xbh4-0 vcvyP TextInput-wrapper prc-components-TextInputWrapper-i1ofR prc-components-TextInputBaseWrapper-ueK9q" data-leading-visual="true" data-trailing-visual="true" aria-busy="false"><span class="TextInput-icon" id=":R2j5ab:" aria-hidden="true"><svg aria-hidden="true" focusable="false" class="octicon octicon-search" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path></svg></span><input type="text" aria-label="Go to file" role="combobox" aria-controls="file-results-list" aria-expanded="false" aria-haspopup="dialog" autoCorrect="off" spellcheck="false" placeholder="Go to file" aria-describedby=":R2j5ab: :R2j5abH1:" data-component="input" class="prc-components-Input-Ic-y8" value=""/><span class="TextInput-icon" id=":R2j5abH1:" aria-hidden="true"></span></span></div><!--/$--></div><div class="Box-sc-g0xbh4-0 YUPas"><button type="button" class="prc-Button-ButtonBase-c50BI" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-describedby=":Rr5ab:-loading-announcement"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-HKbr-"><span data-component="text" class="prc-Button-Label-pTQ3x">Go to file</span></span></button></div><div class="react-directory-add-file-icon"></div><div class="react-directory-remove-file-icon"></div></div><button type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-c50BI" data-loading="false" data-size="medium" data-variant="primary" aria-describedby=":R55ab:-loading-announcement" id=":R55ab:"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-HKbr-"><span data-component="leadingVisual" class="prc-Button-Visual-2epfX prc-Button-VisualWrap-Db-eB"><svg aria-hidden="true" focusable="false" class="octicon octicon-code hide-sm" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path></svg></span><span data-component="text" class="prc-Button-Label-pTQ3x">Code</span><span data-component="trailingVisual" class="prc-Button-Visual-2epfX prc-Button-VisualWrap-Db-eB"><svg aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></span></button><div class="Box-sc-g0xbh4-0 izFOf"><button data-component="IconButton" type="button" aria-label="Open more actions menu" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-c50BI prc-Button-IconButton-szpyj" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-describedby=":R75ab:-loading-announcement" id=":R75ab:"><svg aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button></div></div></div><div data-testid="branch-info-bar" aria-live="polite" class="Box-sc-g0xbh4-0 cjVDqW"><div style="width:40%" class="Skeleton Skeleton--text"> </div><div style="width:30%" class="Skeleton Skeleton--text"> </div></div><div class="Box-sc-g0xbh4-0 vIPPs"><div data-hpc="true"><button hidden="" data-testid="focus-next-element-button" data-hotkey="j"></button><button hidden="" data-testid="focus-previous-element-button" data-hotkey="k"></button><h2 class="sr-only ScreenReaderHeading-module__userSelectNone--vW4Cq prc-Heading-Heading-6CmGO" data-testid="screen-reader-heading" id="folders-and-files">Folders and files</h2><table aria-labelledby="folders-and-files" class="Box-sc-g0xbh4-0 fdROMU"><thead class="Box-sc-g0xbh4-0 jGKpsv"><tr class="Box-sc-g0xbh4-0 jdgHnn"><th colSpan="2" class="Box-sc-g0xbh4-0 bQivRW"><span class="text-bold">Name</span></th><th colSpan="1" class="Box-sc-g0xbh4-0 ldkMIO"><span class="text-bold">Name</span></th><th class="hide-sm"><div title="Last commit message" class="Truncate__StyledTruncate-sc-23o1d2-0 liVpTx width-fit"><span class="text-bold">Last commit message</span></div></th><th colSpan="1" class="Box-sc-g0xbh4-0 jMbWeI"><div title="Last commit date" class="Truncate__StyledTruncate-sc-23o1d2-0 liVpTx width-fit"><span class="text-bold">Last commit date</span></div></th></tr></thead><tbody><tr class="Box-sc-g0xbh4-0 gpqjiB"><td colSpan="3" class="bgColor-muted p-1 rounded-top-2"><div class="Box-sc-g0xbh4-0 dzCJzi"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone--vW4Cq prc-Heading-Heading-6CmGO" data-testid="screen-reader-heading">Latest commit</h2><div style="width:120px" class="Skeleton Skeleton--text" data-testid="loading"> </div><div class="d-flex flex-shrink-0 gap-2"><div data-testid="latest-commit-details" class="d-none d-sm-flex flex-items-center"></div><div class="d-flex gap-2"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone--vW4Cq prc-Heading-Heading-6CmGO" data-testid="screen-reader-heading">History</h2><a href="/ladjs/lad/commits/snyk-fix-bed97d0c625fc25446b4c14528f312d1/" class="prc-Button-ButtonBase-c50BI d-none d-lg-flex LinkButton-module__code-view-link-button--xvCGA flex-items-center fgColor-default" data-loading="false" data-size="small" data-variant="invisible" aria-describedby=":Raqj8pab:-loading-announcement"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-HKbr-"><span data-component="leadingVisual" class="prc-Button-Visual-2epfX prc-Button-VisualWrap-Db-eB"><svg aria-hidden="true" focusable="false" class="octicon octicon-history" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg></span><span data-component="text" class="prc-Button-Label-pTQ3x"><span class="fgColor-default">344 Commits</span></span></span></a><div class="d-sm-none"></div><div class="d-flex d-lg-none"><span role="tooltip" aria-label="344 Commits" id="history-icon-button-tooltip" class="Tooltip__TooltipBase-sc-17tf59c-0 hWlpPn tooltipped-n"><a href="/ladjs/lad/commits/snyk-fix-bed97d0c625fc25446b4c14528f312d1/" class="prc-Button-ButtonBase-c50BI LinkButton-module__code-view-link-button--xvCGA flex-items-center fgColor-default" data-loading="false" data-size="small" data-variant="invisible" aria-describedby=":R1iqj8pab:-loading-announcement history-icon-button-tooltip"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-HKbr-"><span data-component="leadingVisual" class="prc-Button-Visual-2epfX prc-Button-VisualWrap-Db-eB"><svg aria-hidden="true" focusable="false" class="octicon octicon-history" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg></span></span></a></span></div></div></div></div></td></tr><tr class="react-directory-row undefined" id="folder-row-0"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file-directory-fill icon-directory" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.75 1A1.75 1.75 0 0 0 0 2.75v10.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0 0 16 13.25v-8.5A1.75 1.75 0 0 0 14.25 3H7.5a.25.25 0 0 1-.2-.1l-.9-1.2C6.07 1.26 5.55 1 5 1H1.75Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".github" aria-label=".github, (Directory)" class="Link--primary" href="/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.github">.github</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file-directory-fill icon-directory" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.75 1A1.75 1.75 0 0 0 0 2.75v10.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0 0 16 13.25v-8.5A1.75 1.75 0 0 0 14.25 3H7.5a.25.25 0 0 1-.2-.1l-.9-1.2C6.07 1.26 5.55 1 5 1H1.75Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".github" aria-label=".github, (Directory)" class="Link--primary" href="/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.github">.github</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row undefined" id="folder-row-1"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file-directory-fill icon-directory" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.75 1A1.75 1.75 0 0 0 0 2.75v10.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0 0 16 13.25v-8.5A1.75 1.75 0 0 0 14.25 3H7.5a.25.25 0 0 1-.2-.1l-.9-1.2C6.07 1.26 5.55 1 5 1H1.75Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="media" aria-label="media, (Directory)" class="Link--primary" href="/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1/media">media</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file-directory-fill icon-directory" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.75 1A1.75 1.75 0 0 0 0 2.75v10.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0 0 16 13.25v-8.5A1.75 1.75 0 0 0 14.25 3H7.5a.25.25 0 0 1-.2-.1l-.9-1.2C6.07 1.26 5.55 1 5 1H1.75Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="media" aria-label="media, (Directory)" class="Link--primary" href="/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1/media">media</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row undefined" id="folder-row-2"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file-directory-fill icon-directory" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.75 1A1.75 1.75 0 0 0 0 2.75v10.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0 0 16 13.25v-8.5A1.75 1.75 0 0 0 14.25 3H7.5a.25.25 0 0 1-.2-.1l-.9-1.2C6.07 1.26 5.55 1 5 1H1.75Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="template" aria-label="template, (Directory)" class="Link--primary" href="/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template">template</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file-directory-fill icon-directory" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.75 1A1.75 1.75 0 0 0 0 2.75v10.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0 0 16 13.25v-8.5A1.75 1.75 0 0 0 14.25 3H7.5a.25.25 0 0 1-.2-.1l-.9-1.2C6.07 1.26 5.55 1 5 1H1.75Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="template" aria-label="template, (Directory)" class="Link--primary" href="/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template">template</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row undefined" id="folder-row-3"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file-directory-fill icon-directory" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.75 1A1.75 1.75 0 0 0 0 2.75v10.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0 0 16 13.25v-8.5A1.75 1.75 0 0 0 14.25 3H7.5a.25.25 0 0 1-.2-.1l-.9-1.2C6.07 1.26 5.55 1 5 1H1.75Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="test" aria-label="test, (Directory)" class="Link--primary" href="/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1/test">test</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file-directory-fill icon-directory" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.75 1A1.75 1.75 0 0 0 0 2.75v10.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0 0 16 13.25v-8.5A1.75 1.75 0 0 0 14.25 3H7.5a.25.25 0 0 1-.2-.1l-.9-1.2C6.07 1.26 5.55 1 5 1H1.75Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="test" aria-label="test, (Directory)" class="Link--primary" href="/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1/test">test</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row undefined" id="folder-row-4"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".browserslistrc" aria-label=".browserslistrc, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.browserslistrc">.browserslistrc</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".browserslistrc" aria-label=".browserslistrc, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.browserslistrc">.browserslistrc</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row undefined" id="folder-row-5"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".editorconfig" aria-label=".editorconfig, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.editorconfig">.editorconfig</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".editorconfig" aria-label=".editorconfig, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.editorconfig">.editorconfig</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row undefined" id="folder-row-6"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".gitattributes" aria-label=".gitattributes, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.gitattributes">.gitattributes</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".gitattributes" aria-label=".gitattributes, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.gitattributes">.gitattributes</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row undefined" id="folder-row-7"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".gitignore" aria-label=".gitignore, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.gitignore">.gitignore</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".gitignore" aria-label=".gitignore, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.gitignore">.gitignore</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row undefined" id="folder-row-8"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".lintstagedrc.js" aria-label=".lintstagedrc.js, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.lintstagedrc.js">.lintstagedrc.js</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".lintstagedrc.js" aria-label=".lintstagedrc.js, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.lintstagedrc.js">.lintstagedrc.js</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row undefined" id="folder-row-9"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".nojekyll" aria-label=".nojekyll, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.nojekyll">.nojekyll</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".nojekyll" aria-label=".nojekyll, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.nojekyll">.nojekyll</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row truncate-for-mobile" id="folder-row-10"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".npmignore" aria-label=".npmignore, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.npmignore">.npmignore</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".npmignore" aria-label=".npmignore, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.npmignore">.npmignore</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row truncate-for-mobile" id="folder-row-11"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".npmrc" aria-label=".npmrc, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.npmrc">.npmrc</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".npmrc" aria-label=".npmrc, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.npmrc">.npmrc</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row truncate-for-mobile" id="folder-row-12"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".remarkignore" aria-label=".remarkignore, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.remarkignore">.remarkignore</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".remarkignore" aria-label=".remarkignore, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.remarkignore">.remarkignore</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row truncate-for-mobile" id="folder-row-13"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".travis.yml" aria-label=".travis.yml, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.travis.yml">.travis.yml</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title=".travis.yml" aria-label=".travis.yml, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.travis.yml">.travis.yml</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row truncate-for-mobile" id="folder-row-14"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="CNAME" aria-label="CNAME, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/CNAME">CNAME</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="CNAME" aria-label="CNAME, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/CNAME">CNAME</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row truncate-for-mobile" id="folder-row-15"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="LICENSE" aria-label="LICENSE, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/LICENSE">LICENSE</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="LICENSE" aria-label="LICENSE, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/LICENSE">LICENSE</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row truncate-for-mobile" id="folder-row-16"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="README.md" aria-label="README.md, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/README.md">README.md</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="README.md" aria-label="README.md, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/README.md">README.md</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row truncate-for-mobile" id="folder-row-17"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="cli.js" aria-label="cli.js, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/cli.js">cli.js</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="cli.js" aria-label="cli.js, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/cli.js">cli.js</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row truncate-for-mobile" id="folder-row-18"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="config.js" aria-label="config.js, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/config.js">config.js</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="config.js" aria-label="config.js, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/config.js">config.js</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row truncate-for-mobile" id="folder-row-19"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="favicon.ico" aria-label="favicon.ico, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/favicon.ico">favicon.ico</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="favicon.ico" aria-label="favicon.ico, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/favicon.ico">favicon.ico</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row truncate-for-mobile" id="folder-row-20"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="index.html" aria-label="index.html, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/index.html">index.html</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="index.html" aria-label="index.html, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/index.html">index.html</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row truncate-for-mobile" id="folder-row-21"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="package.json" aria-label="package.json, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/package.json">package.json</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="package.json" aria-label="package.json, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/package.json">package.json</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row truncate-for-mobile" id="folder-row-22"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="sao.js" aria-label="sao.js, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/sao.js">sao.js</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="sao.js" aria-label="sao.js, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/sao.js">sao.js</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="react-directory-row truncate-for-mobile" id="folder-row-23"><td class="react-directory-row-name-cell-small-screen" colSpan="2"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="yarn.lock" aria-label="yarn.lock, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/yarn.lock">yarn.lock</a></div></div></div></div></td><td class="react-directory-row-name-cell-large-screen" colSpan="1"><div class="react-directory-filename-column"><svg aria-hidden="true" focusable="false" class="octicon octicon-file color-fg-muted" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"></path></svg><div class="overflow-hidden"><div class="react-directory-filename-cell"><div class="react-directory-truncate"><a title="yarn.lock" aria-label="yarn.lock, (File)" class="Link--primary" href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/yarn.lock">yarn.lock</a></div></div></div></div></td><td class="react-directory-row-commit-cell"><div class="Skeleton Skeleton--text"> </div></td><td><div class="Skeleton Skeleton--text"> </div></td></tr><tr class="Box-sc-g0xbh4-0 eNCcrz show-for-mobile" data-testid="view-all-files-row"><td colSpan="3" class="Box-sc-g0xbh4-0 bHTcCe"><div><button class="prc-Link-Link-85e08">View all files</button></div></td></tr></tbody></table></div><div class="Box-sc-g0xbh4-0 csrIcr"><div class="Box-sc-g0xbh4-0 bUQNHB"><div itemscope="" itemType="https://schema.org/abstract" class="Box-sc-g0xbh4-0 jPdcfu"><h2 class="_VisuallyHidden__VisuallyHidden-sc-11jhm7a-0 brGdpi">Repository files navigation</h2><nav class="Box-sc-g0xbh4-0 iphEWz prc-components-UnderlineWrapper-oOh5J" aria-label="Repository files"><ul class="prc-components-UnderlineItemList-b23Hf" role="list"><li class="Box-sc-g0xbh4-0 hUCRAk"><a class="prc-components-UnderlineItem-lJsg-" href="#" aria-current="page"><span data-component="icon"><svg aria-hidden="true" focusable="false" class="octicon octicon-book" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 1.75A.75.75 0 0 1 .75 1h4.253c1.227 0 2.317.59 3 1.501A3.743 3.743 0 0 1 11.006 1h4.245a.75.75 0 0 1 .75.75v10.5a.75.75 0 0 1-.75.75h-4.507a2.25 2.25 0 0 0-1.591.659l-.622.621a.75.75 0 0 1-1.06 0l-.622-.621A2.25 2.25 0 0 0 5.258 13H.75a.75.75 0 0 1-.75-.75Zm7.251 10.324.004-5.073-.002-2.253A2.25 2.25 0 0 0 5.003 2.5H1.5v9h3.757a3.75 3.75 0 0 1 1.994.574ZM8.755 4.75l-.004 7.322a3.752 3.752 0 0 1 1.992-.572H14.5v-9h-3.495a2.25 2.25 0 0 0-2.25 2.25Z"></path></svg></span><span data-component="text" data-content="README">README</span></a></li><li class="Box-sc-g0xbh4-0 hUCRAk"><a class="prc-components-UnderlineItem-lJsg-" href="#"><span data-component="icon"><svg aria-hidden="true" focusable="false" class="octicon octicon-code-of-conduct" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8.048 2.241c.964-.709 2.079-1.238 3.325-1.241a4.616 4.616 0 0 1 3.282 1.355c.41.408.757.86.996 1.428.238.568.348 1.206.347 1.968 0 2.193-1.505 4.254-3.081 5.862-1.496 1.526-3.213 2.796-4.249 3.563l-.22.163a.749.749 0 0 1-.895 0l-.221-.163c-1.036-.767-2.753-2.037-4.249-3.563C1.51 10.008.007 7.952.002 5.762a4.614 4.614 0 0 1 1.353-3.407C3.123.585 6.223.537 8.048 2.24Zm-1.153.983c-1.25-1.033-3.321-.967-4.48.191a3.115 3.115 0 0 0-.913 2.335c0 1.556 1.109 3.24 2.652 4.813C5.463 11.898 6.96 13.032 8 13.805c.353-.262.758-.565 1.191-.905l-1.326-1.223a.75.75 0 0 1 1.018-1.102l1.48 1.366c.328-.281.659-.577.984-.887L9.99 9.802a.75.75 0 1 1 1.019-1.103l1.384 1.28c.295-.329.566-.661.81-.995L12.92 8.7l-1.167-1.168c-.674-.671-1.78-.664-2.474.03-.268.269-.538.537-.802.797-.893.882-2.319.843-3.185-.032-.346-.35-.693-.697-1.043-1.047a.75.75 0 0 1-.04-1.016c.162-.191.336-.401.52-.623.62-.748 1.356-1.637 2.166-2.417Zm7.112 4.442c.313-.65.491-1.293.491-1.916v-.001c0-.614-.088-1.045-.23-1.385-.143-.339-.357-.633-.673-.949a3.111 3.111 0 0 0-2.218-.915c-1.092.003-2.165.627-3.226 1.602-.823.755-1.554 1.637-2.228 2.45l-.127.154.562.566a.755.755 0 0 0 1.066.02l.794-.79c1.258-1.258 3.312-1.31 4.594-.032.396.394.792.791 1.173 1.173Z"></path></svg></span><span data-component="text" data-content="Code of conduct">Code of conduct</span></a></li><li class="Box-sc-g0xbh4-0 hUCRAk"><a class="prc-components-UnderlineItem-lJsg-" href="#"><span data-component="icon"><svg aria-hidden="true" focusable="false" class="octicon octicon-law" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8.75.75V2h.985c.304 0 .603.08.867.231l1.29.736c.038.022.08.033.124.033h2.234a.75.75 0 0 1 0 1.5h-.427l2.111 4.692a.75.75 0 0 1-.154.838l-.53-.53.529.531-.001.002-.002.002-.006.006-.006.005-.01.01-.045.04c-.21.176-.441.327-.686.45C14.556 10.78 13.88 11 13 11a4.498 4.498 0 0 1-2.023-.454 3.544 3.544 0 0 1-.686-.45l-.045-.04-.016-.015-.006-.006-.004-.004v-.001a.75.75 0 0 1-.154-.838L12.178 4.5h-.162c-.305 0-.604-.079-.868-.231l-1.29-.736a.245.245 0 0 0-.124-.033H8.75V13h2.5a.75.75 0 0 1 0 1.5h-6.5a.75.75 0 0 1 0-1.5h2.5V3.5h-.984a.245.245 0 0 0-.124.033l-1.289.737c-.265.15-.564.23-.869.23h-.162l2.112 4.692a.75.75 0 0 1-.154.838l-.53-.53.529.531-.001.002-.002.002-.006.006-.016.015-.045.04c-.21.176-.441.327-.686.45C4.556 10.78 3.88 11 3 11a4.498 4.498 0 0 1-2.023-.454 3.544 3.544 0 0 1-.686-.45l-.045-.04-.016-.015-.006-.006-.004-.004v-.001a.75.75 0 0 1-.154-.838L2.178 4.5H1.75a.75.75 0 0 1 0-1.5h2.234a.249.249 0 0 0 .125-.033l1.288-.737c.265-.15.564-.23.869-.23h.984V.75a.75.75 0 0 1 1.5 0Zm2.945 8.477c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L13 6.327Zm-10 0c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L3 6.327Z"></path></svg></span><span data-component="text" data-content="License">License</span></a></li><li class="Box-sc-g0xbh4-0 hUCRAk"><a class="prc-components-UnderlineItem-lJsg-" href="#"><span data-component="icon"><svg aria-hidden="true" focusable="false" class="octicon octicon-law" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8.75.75V2h.985c.304 0 .603.08.867.231l1.29.736c.038.022.08.033.124.033h2.234a.75.75 0 0 1 0 1.5h-.427l2.111 4.692a.75.75 0 0 1-.154.838l-.53-.53.529.531-.001.002-.002.002-.006.006-.006.005-.01.01-.045.04c-.21.176-.441.327-.686.45C14.556 10.78 13.88 11 13 11a4.498 4.498 0 0 1-2.023-.454 3.544 3.544 0 0 1-.686-.45l-.045-.04-.016-.015-.006-.006-.004-.004v-.001a.75.75 0 0 1-.154-.838L12.178 4.5h-.162c-.305 0-.604-.079-.868-.231l-1.29-.736a.245.245 0 0 0-.124-.033H8.75V13h2.5a.75.75 0 0 1 0 1.5h-6.5a.75.75 0 0 1 0-1.5h2.5V3.5h-.984a.245.245 0 0 0-.124.033l-1.289.737c-.265.15-.564.23-.869.23h-.162l2.112 4.692a.75.75 0 0 1-.154.838l-.53-.53.529.531-.001.002-.002.002-.006.006-.016.015-.045.04c-.21.176-.441.327-.686.45C4.556 10.78 3.88 11 3 11a4.498 4.498 0 0 1-2.023-.454 3.544 3.544 0 0 1-.686-.45l-.045-.04-.016-.015-.006-.006-.004-.004v-.001a.75.75 0 0 1-.154-.838L2.178 4.5H1.75a.75.75 0 0 1 0-1.5h2.234a.249.249 0 0 0 .125-.033l1.288-.737c.265-.15.564-.23.869-.23h.984V.75a.75.75 0 0 1 1.5 0Zm2.945 8.477c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L13 6.327Zm-10 0c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L3 6.327Z"></path></svg></span><span data-component="text" data-content="Security">Security</span></a></li></ul></nav><button style="--button-color:fg.subtle" type="button" aria-label="Outline" aria-haspopup="true" aria-expanded="false" tabindex="0" class="Box-sc-g0xbh4-0 cwoBXV prc-Button-ButtonBase-c50BI" data-loading="false" data-size="medium" data-variant="invisible" aria-describedby=":Rr9ab:-loading-announcement" id=":Rr9ab:"><svg aria-hidden="true" focusable="false" class="octicon octicon-list-unordered" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M5.75 2.5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5Zm0 5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5Zm0 5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5ZM2 14a1 1 0 1 1 0-2 1 1 0 0 1 0 2Zm1-6a1 1 0 1 1-2 0 1 1 0 0 1 2 0ZM2 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg></button></div><div class="Box-sc-g0xbh4-0 QkQOb js-snippet-clipboard-copy-unpositioned undefined" data-hpc="true"><article class="markdown-body entry-content container-lg" itemprop="text"><div class="markdown-heading" dir="auto"><h1 align="center" tabindex="-1" class="heading-element" dir="auto"> <a href="https://ladjs.github.io/lad/" rel="nofollow"><img src="/ladjs/lad/raw/snyk-fix-bed97d0c625fc25446b4c14528f312d1/media/lad.png" alt="lad" style="max-width: 100%;"></a> </h1><a id="user-content---" class="anchor" aria-label="Permalink: " href="#--"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <div align="center" dir="auto"> <a href="https://join.slack.com/t/ladjs/shared_invite/zt-fqei6z11-Bq2trhwHQxVc5x~ifiZG0g" rel="nofollow"><img src="https://camo.githubusercontent.com/6dd9e714205d1d4bacbf2c6a04fe9fa2a33208a1c6babf547101166d0d5c0e81/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636861742d6a6f696e253230736c61636b2d627269676874677265656e" alt="chat" data-canonical-src="https://img.shields.io/badge/chat-join%20slack-brightgreen" style="max-width: 100%;"></a> <a href="https://travis-ci.org/ladjs/lad" rel="nofollow"><img src="https://camo.githubusercontent.com/c08a0dabec4436cf3029dc17c37f395d32eff7f05120f178f3bcf04fd8731f20/68747470733a2f2f7472617669732d63692e6f72672f6c61646a732f6c61642e7376673f6272616e63683d6d6173746572" alt="build status" data-canonical-src="https://travis-ci.org/ladjs/lad.svg?branch=master" style="max-width: 100%;"></a> <a href="https://codecov.io/github/ladjs/lad" rel="nofollow"><img src="https://camo.githubusercontent.com/cb18625953f4cfccd27732129da5d4329bab291dd745fc148776c8ade3113c62/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f6c61646a732f6c61642f6d61737465722e737667" alt="code coverage" data-canonical-src="https://img.shields.io/codecov/c/github/ladjs/lad/master.svg" style="max-width: 100%;"></a> <a href="https://github.com/sindresorhus/xo"><img src="https://camo.githubusercontent.com/e40c657b8e9f62e24c6806f6221b4deec91873208ff9d78c9acb75baa843b66a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f64655f7374796c652d584f2d3565643963372e737667" alt="code style" data-canonical-src="https://img.shields.io/badge/code_style-XO-5ed9c7.svg" style="max-width: 100%;"></a> <a href="https://github.com/prettier/prettier"><img src="https://camo.githubusercontent.com/3bacc065fff241f323175f9ddb92715c4a989b9d8c70321a0c3823e9d7ba8fea/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7374796c65645f776974682d70726574746965722d6666363962342e737667" alt="styled with prettier" data-canonical-src="https://img.shields.io/badge/styled_with-prettier-ff69b4.svg" style="max-width: 100%;"></a> <a href="https://lass.js.org" rel="nofollow"><img src="https://camo.githubusercontent.com/fc8ee60db54e388140d708db4d01b2d90522265847e077b22fc4cd09b0fe68f0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6d6164655f776974682d6c6173732d3935434332382e737667" alt="made with lass" data-canonical-src="https://img.shields.io/badge/made_with-lass-95CC28.svg" style="max-width: 100%;"></a> <a href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/LICENSE"><img src="https://camo.githubusercontent.com/8468249e3d59c31fee6c1c0bffd23df0185ff41bc9888f485f4469bc72073865/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6c61646a732f6c61642e737667" alt="license" data-canonical-src="https://img.shields.io/github/license/ladjs/lad.svg" style="max-width: 100%;"></a> </div> <br> <div align="center" dir="auto"> Lad is the best <a href="https://nodejs.org" rel="nofollow">Node.js</a> framework. Made by a former <a href="https://github.com/expressjs/express">Express</a> TC and <a href="https://github.com/koajs/koa">Koa</a> team member. </div> <div align="center" dir="auto"> <sub> A lad that fell in love with a <a href="https://lass.js.org" rel="nofollow"><strong>lass</strong></a> • Built by <a href="https://github.com/niftylettuce">@niftylettuce</a> and <a href="#contributors">contributors</a> </sub> </div> <hr> <div align="center" dir="auto"> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Project Spotlight: Forward Email @ <a href="https://forwardemail.net" rel="nofollow">https://forwardemail.net</a> (made with Lad)</h3><a id="user-content-project-spotlight-forward-email--httpsforwardemailnet-made-with-lad" class="anchor" aria-label="Permalink: Project Spotlight: Forward Email @ https://forwardemail.net (made with Lad)" href="#project-spotlight-forward-email--httpsforwardemailnet-made-with-lad"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Live Framework Demo: <a href="https://lad.sh" rel="nofollow">https://lad.sh</a></h4><a id="user-content-live-framework-demo-httpsladsh" class="anchor" aria-label="Permalink: Live Framework Demo:https://lad.sh" href="#live-framework-demo-httpsladsh"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> </div> <hr> <div align="center" dir="auto">❤️ Love this project? Support <a href="https://github.com/niftylettuce">@niftylettuce's</a> <a href="https://en.wikipedia.org/wiki/Free_and_open-source_software" rel="nofollow">FOSS</a> on <a href="https://patreon.com/niftylettuce" rel="nofollow">Patreon</a> or <a href="https://paypal.me/niftylettuce" rel="nofollow">PayPal</a> 🦄</div> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Table of Contents</h2><a id="user-content-table-of-contents" class="anchor" aria-label="Permalink: Table of Contents" href="#table-of-contents"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <ul dir="auto"> <li><a href="#features">Features</a> <ul dir="auto"> <li><a href="#microservices">Microservices</a></li> <li><a href="#front-end">Front-end</a></li> <li><a href="#back-end">Back-end</a></li> <li><a href="#translation">Translation</a></li> <li><a href="#email-engine">Email Engine</a></li> <li><a href="#error-handling">Error Handling</a></li> <li><a href="#performance">Performance</a></li> <li><a href="#security">Security</a></li> </ul> </li> <li><a href="#get-started">Get Started</a> <ul dir="auto"> <li><a href="#requirements">Requirements</a></li> <li><a href="#install">Install</a></li> <li><a href="#usage">Usage</a></li> <li><a href="#configuration">Configuration</a></li> <li><a href="#tutorials">Tutorials</a></li> <li><a href="#community">Community</a></li> </ul> </li> <li><a href="#architecture">Architecture</a></li> <li><a href="#principles">Principles</a></li> <li><a href="#related">Related</a></li> <li><a href="#contributing">Contributing</a></li> <li><a href="#contributors">Contributors</a></li> <li><a href="#trademark-notice">Trademark Notice</a></li> <li><a href="#license">License</a></li> </ul> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Features</h2><a id="user-content-features" class="anchor" aria-label="Permalink: Features" href="#features"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">Lad boasts dozens of features and is extremely configurable.</p> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Microservices</h3><a id="user-content-microservices" class="anchor" aria-label="Permalink: Microservices" href="#microservices"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">These microservices are preconfigured for security, performance, and graceful reloading.</p> <ul dir="auto"> <li>Webapp server → <a href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/web.js">web.js</a></li> <li>API server → <a href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/api.js">api.js</a></li> <li>Job scheduler → <a href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/bree.js">bree.js</a></li> <li>Proxy server → <a href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/proxy.js">proxy.js</a></li> </ul> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Front-end</h3><a id="user-content-front-end" class="anchor" aria-label="Permalink: Front-end" href="#front-end"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <ul dir="auto"> <li>Browser linting using <a href="https://github.com/amilajack/eslint-plugin-compat">eslint-plugin-compat</a> and <a href="https://github.com/ai/browserslist">browserslist</a> (see <a href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/.browserslistrc">.browserslistrc</a> for the default config)</li> <li><a href="https://pugjs.org" rel="nofollow">Pug</a> template engine (you can easily use <a href="https://github.com/kbrsh/moon">Moon</a>, <a href="https://vuejs.org/" rel="nofollow">Vue</a>, <a href="https://facebook.github.io/react/" rel="nofollow">React</a>, or <a href="https://angular.io/" rel="nofollow">Angular</a>, though typically <a href="https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it" rel="nofollow">you aren't going to need it</a>)</li> <li><a href="https://gulpjs.com" rel="nofollow">Gulp</a> (latest version 4.x)</li> <li><a href="http://sass-lang.com/" rel="nofollow">Sass</a></li> <li><a href="http://postcss.org/" rel="nofollow">PostCSS</a> (with <a href="https://github.com/jonathantneal/postcss-font-magician">font-magician</a>, <a href="https://github.com/unlight/postcss-import-url">import-url</a>, <a href="https://github.com/AaronJan/postcss-font-grabber">font-grabber</a>, <a href="https://github.com/jelmerdemaat/postcss-base64">base64</a>, and <a href="http://cssnext.io/" rel="nofollow">cssnext</a> pre-configured)</li> <li><a href="https://getbootstrap.com/" rel="nofollow">Bootstrap</a></li> <li><a href="http://fontawesome.io/" rel="nofollow">Font Awesome</a></li> <li><a href="http://tobiasahlin.com/spinkit/" rel="nofollow">SpinKit</a></li> <li><a href="https://limonte.github.io/sweetalert2/" rel="nofollow">SweetAlert2</a></li> <li><a href="http://dense.rah.pw/" rel="nofollow">Dense</a></li> <li><a href="http://imakewebthings.com/waypoints/" rel="nofollow">Waypoints</a></li> <li><a href="https://github.com/intesso/connect-livereload">LiveReload</a></li> <li>…</li> </ul> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Back-end</h3><a id="user-content-back-end" class="anchor" aria-label="Permalink: Back-end" href="#back-end"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <ul dir="auto"> <li>Redis, sessions, and flash toast and modal <a href="https://limonte.github.io/sweetalert2/" rel="nofollow">SweetAlert2</a> messages (uses <a href="https://github.com/luin/ioredis">ioredis</a> which has support for <a href="https://redis.io/topics/cluster-tutorial" rel="nofollow">Cluster</a>, <a href="https://redis.io/topics/sentinel" rel="nofollow">Sentinel</a>, and more)</li> <li>Koa-based webapp and API servers (uses HTTP/2 for production!)</li> <li>Pagination built-in (using <a href="https://github.com/koajs/ctx-paginate">ctx-paginate</a>)</li> <li>RESTful API with BasicAuth and versioning</li> <li>Automated job scheduler with cron and human-readable syntax (backed by <a href="http://mongoosejs.com" rel="nofollow">Mongoose</a> and <a href="https://jobscheduler.net" rel="nofollow">Bree</a>)</li> <li>Passport-based authentication and group-based (Unix-like) permissioning</li> <li>Stripe-inspired error handling</li> <li>Mongoose and MongoDB with common database plugins</li> <li>Email template engine with <a href="https://nodemailer.com/" rel="nofollow">Nodemailer</a> and local rendering</li> <li>Proxy eliminates need for Nginx reverse-proxy or Apache virtual hosts</li> <li>Multilingual through built-in i18n translation support (<a href="#translation-configuration">see configuration</a>)</li> <li>Automatic phrase translation with Google Translate</li> <li>Sitemap generator for simple SEO</li> <li>…</li> </ul> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Translation</h3><a id="user-content-translation" class="anchor" aria-label="Permalink: Translation" href="#translation"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">Finally a framework that solves i18n everywhere; complete with automatic translation.</p> <ul dir="auto"> <li>Translation constants built-in so you <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself" rel="nofollow">don't repeat yourself</a></li> <li>Webapp error messages and templates are translated</li> <li>Emails are translated</li> <li>API responses are translated</li> <li>Database errors are translated</li> <li>Authentication errors are translated</li> <li>…</li> </ul> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Email Engine</h3><a id="user-content-email-engine" class="anchor" aria-label="Permalink: Email Engine" href="#email-engine"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">Our beautiful email engine uses <a href="https://github.com/niftylettuce/node-email-templates">email-templates</a> (which is also made by the creator of Lad)!</p> <ul dir="auto"> <li>Test your emails locally with automatic browser-rendering on the fly</li> <li>Automatically inlines CSS for cross-browser and cross-platform email client support</li> <li>Use <a href="https://getbootstrap.com/" rel="nofollow">Bootstrap</a> in your email template designs</li> <li>Reuse your existing CSS and webapp styling</li> <li>Use any template engine (defaults to Pug)</li> <li><a href="https://github.com/ladjs/custom-fonts-in-emails">Render custom fonts in emails with code</a></li> <li><a href="https://github.com/ladjs/font-awesome-assets">Add icons with Font Awesome with code</a></li> <li><a href="https://github.com/ladjs/nodemailer-base64-to-s3">Automatically avoid email client caching</a></li> <li>Include any image you want and it will be properly rendered</li> <li>Rids the need for awkward embedded image CID attachments</li> <li>…</li> </ul> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Error Handling</h3><a id="user-content-error-handling" class="anchor" aria-label="Permalink: Error Handling" href="#error-handling"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">We've spent a lot of time designing a beautiful error handler.</p> <ul dir="auto"> <li>Supports <code>text/html</code>, <code>application/json</code>, and <code>text</code> response types</li> <li><a href="https://github.com/niftylettuce/koa-better-error-handler#user-friendly-responses">User-friendly responses</a></li> <li><a href="https://github.com/niftylettuce/koa-better-error-handler#html-error-lists">HTML error lists</a></li> <li>…</li> </ul> <p dir="auto">See <a href="https://github.com/niftylettuce/koa-better-error-handler">koa-better-error-handler</a> for a complete reference.</p> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Performance</h3><a id="user-content-performance" class="anchor" aria-label="Permalink: Performance" href="#performance"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <ul dir="auto"> <li>Compression and zero-bloat approach</li> <li>Stream-based file uploading</li> <li>Graceful reloading, shutdown, and reconnection handling</li> <li>Manifest asset revisioning</li> <li>Amazon S3 and CloudFront ready</li> <li>…</li> </ul> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Security</h3><a id="user-content-security" class="anchor" aria-label="Permalink: Security" href="#security"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <ul dir="auto"> <li>Database security plugins and helpers</li> <li>Automated tests and code coverage</li> <li>CORS, SameSite set to "lax" (<a href="https://scotthelme.co.uk/csrf-is-dead/" rel="nofollow">an alternative to CSRF</a>), CSRF (since <a href="https://caniuse.com/#search=SameSite" rel="nofollow">not all browsers</a> support SameSite yet) XSS, and rate limited protection</li> <li>Dotenv support for environment-based configurations</li> <li>App, user, and request-based logging</li> <li>SSL-ready (see <a href="#ssl-configuration">instructions below</a>)</li> <li>…</li> </ul> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Get Started</h2><a id="user-content-get-started" class="anchor" aria-label="Permalink: Get Started" href="#get-started"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">We strictly support Mac and Ubuntu-based operating systems (we do not support Windows).</p> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Requirements</h3><a id="user-content-requirements" class="anchor" aria-label="Permalink: Requirements" href="#requirements"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">Please ensure your operating system has the following software installed:</p> <ul dir="auto"> <li> <p dir="auto"><a href="https://git-scm.com/" rel="nofollow">Git</a> - see <a href="https://help.github.com/articles/set-up-git/">GitHub's tutorial</a> for installation</p> </li> <li> <p dir="auto"><a href="https://nodejs.org" rel="nofollow">Node.js</a> (v10+) - use <a href="https://github.com/creationix/nvm">nvm</a> to install it on any OS</p> <ul dir="auto"> <li>After installing <code>nvm</code> you will need to run <code>nvm install node</code></li> <li>We also recommend you install <a href="https://yarnpkg.com/" rel="nofollow">yarn</a>, which is an alternative to <a href="https://www.npmjs.com/" rel="nofollow">npm</a></li> </ul> </li> <li> <p dir="auto"><a href="https://www.mongodb.com/" rel="nofollow">MongoDB</a> (v3.x+):</p> <ul dir="auto"> <li> <p dir="auto">Mac (via <a href="https://brew.sh/" rel="nofollow">brew</a>): <code>brew tap mongodb/brew &amp;&amp; brew install mongodb-community &amp;&amp; brew services start mongodb-community</code>.</p> </li> <li> <p dir="auto">Ubuntu:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6 echo &quot;deb http://repo.mongodb.org/apt/ubuntu &quot;$(lsb_release -sc)&quot;/mongodb-org/3.4 multiverse&quot; | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list sudo apt-get update sudo apt-get -y install mongodb-org"><pre>sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6 <span class="pl-c1">echo</span> <span class="pl-s"><span class="pl-pds">"</span>deb http://repo.mongodb.org/apt/ubuntu <span class="pl-pds">"</span></span><span class="pl-s"><span class="pl-pds">$(</span>lsb_release -sc<span class="pl-pds">)</span></span><span class="pl-s"><span class="pl-pds">"</span>/mongodb-org/3.4 multiverse<span class="pl-pds">"</span></span> <span class="pl-k">|</span> sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list sudo apt-get update sudo apt-get -y install mongodb-org</pre></div> </li> </ul> </li> <li> <p dir="auto"><a href="https://redis.io/" rel="nofollow">Redis</a> (v4.x+):</p> <ul dir="auto"> <li> <p dir="auto">Mac (via <a href="https://brew.sh/" rel="nofollow">brew</a>): <code>brew install redis &amp;&amp; brew services start redis</code></p> </li> <li> <p dir="auto">Ubuntu:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="sudo add-apt-repository -y ppa:chris-lea/redis-server sudo apt-get update sudo apt-get -y install redis-server"><pre>sudo add-apt-repository -y ppa:chris-lea/redis-server sudo apt-get update sudo apt-get -y install redis-server</pre></div> </li> </ul> </li> </ul> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Install</h3><a id="user-content-install" class="anchor" aria-label="Permalink: Install" href="#install"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto"><a href="https://www.npmjs.com/" rel="nofollow">npm</a>:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="npm install -g lad"><pre>npm install -g lad</pre></div> <p dir="auto"><a href="https://yarnpkg.com/" rel="nofollow">yarn</a>:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="yarn global add lad"><pre>yarn global add lad</pre></div> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Usage</h3><a id="user-content-usage" class="anchor" aria-label="Permalink: Usage" href="#usage"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Create a project</h4><a id="user-content-create-a-project" class="anchor" aria-label="Permalink: Create a project" href="#create-a-project"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="lad new-project cd new-project"><pre>lad new-project <span class="pl-c1">cd</span> new-project</pre></div> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Development</h4><a id="user-content-development" class="anchor" aria-label="Permalink: Development" href="#development"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">To begin, try typing <code>npm start</code> (or <code>yarn start</code>) on command line. This will display to you all the scripts you can run.</p> <p dir="auto">The <code>start</code> script (among many others) uses <a href="https://github.com/kentcdodds/nps">nps</a> and <a href="https://github.com/kentcdodds/nps-utils">nps-utils</a> under the hood. This helps to keep scripts very developer-friendly, and rids the need to write in JSON syntax.</p> <p dir="auto">This script accepts a <code>&lt;task&gt;</code> argument, whereas a task of <code>all</code> will spawn, watch, and re-compile all of the <a href="#microservices">microservices</a> mentioned above.</p> <p dir="auto">Just open <a href="http://localhost:3000" rel="nofollow">http://localhost:3000</a> for testing!</p> <p dir="auto"><a href="https://www.npmjs.com/" rel="nofollow">npm</a>:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="npm start all"><pre>npm start all</pre></div> <p dir="auto"><a href="https://yarnpkg.com/" rel="nofollow">yarn</a>:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="yarn start all"><pre>yarn start all</pre></div> <div class="markdown-heading" dir="auto"><h5 tabindex="-1" class="heading-element" dir="auto">Debugging</h5><a id="user-content-debugging" class="anchor" aria-label="Permalink: Debugging" href="#debugging"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <ul dir="auto"> <li> <p dir="auto"><code>DEBUG</code> - debug using <a href="https://github.com/visionmedia/debug">debug</a> output (widely adopted package in the community for debugging across all Node packages):</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="DEBUG=* ..."><pre>DEBUG=<span class="pl-k">*</span> ...</pre></div> </li> <li> <p dir="auto"><code>NODE_DEBUG</code> - debug <a href="https://nodejs.org" rel="nofollow">node</a> internal modules:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="NODE_DEBUG=* ..."><pre>NODE_DEBUG=<span class="pl-k">*</span> ...</pre></div> </li> <li> <p dir="auto"><code>MONGOOSE_DEBUG</code> - debug Mongoose raw database operation output:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="MONGOOSE_DEBUG=true ..."><pre>MONGOOSE_DEBUG=true ...</pre></div> </li> <li> <p dir="auto"><code>TRANSPORT_DEBUG</code> - debug Nodemailer transport:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="TRANSPORT_DEBUG=true ..."><pre>TRANSPORT_DEBUG=true ...</pre></div> </li> <li> <p dir="auto"><code>REDIS_MONITOR</code> - debug Redis using <code>MONITOR</code> (uses <a href="https://github.com/ladjs/redis">@ladjs/redis</a> and passes <code>true</code> for the <code>monitor</code> argument):</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="REDIS_MONITOR=true ..."><pre>REDIS_MONITOR=true ...</pre></div> </li> <li> <p dir="auto"><code>REDIS_FRIENDLY_ERROR_STACK</code> - debug Redis with friendly error stack messages (see <a href="https://github.com/luin/ioredis#error-handling">showFriendlyErrorStack</a> option of <a href="https://github.com/luin/ioredis">ioredis</a>)</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="REDIS_FRIENDLY_ERROR_STACK=true ..."><pre>REDIS_FRIENDLY_ERROR_STACK=true ...</pre></div> </li> </ul> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Production</h4><a id="user-content-production" class="anchor" aria-label="Permalink: Production" href="#production"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">We strongly recommend using <a href="https://semaphoreci.com/?ref=lad" rel="nofollow">SemaphoreCI</a>, <a href="http://pm2.keymetrics.io/" rel="nofollow">PM2</a>, and <a href="https://m.do.co/c/a7fe489d1b27" rel="nofollow">Digital Ocean</a> for production deployment.</p> <ol dir="auto"> <li> <p dir="auto">We've provided you with a preconfigured <a href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/ecosystem.json">ecosystem.json</a> <a href="http://pm2.keymetrics.io/docs/usage/deployment/" rel="nofollow">deployment file</a>. You will need to modify this file with your server's IP, hostname, and other metadata if needed.</p> </li> <li> <p dir="auto">Make sure that your project's assets are built with <code>NODE_ENV=production</code> flag, e.g. <code>NODE_ENV=production npm run build</code> (or with yarn as <code>yarn build</code>);this creates a <code>build/rev-manifest.json</code> file per <a href="https://github.com/niftylettuce/koa-manifest-rev">koa-manifest-rev</a>.</p> </li> <li> <p dir="auto">You can test this locally by installing <a href="http://pm2.keymetrics.io/" rel="nofollow">PM2</a> globally with <a href="https://www.npmjs.com/" rel="nofollow">npm</a> or <a href="https://yarnpkg.com/" rel="nofollow">yarn</a>, and then running the following command:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="NODE_ENV=production pm2 start"><pre>NODE_ENV=production pm2 start</pre></div> </li> <li> <p dir="auto">See the <a href="#continuous-integration-and-code-coverage">Continuous Integration and Code Coverage</a> and <a href="#tutorials">Tutorials</a> sections below for instructions on how to setup continuous integration, code coverage, and deployment.</p> </li> <li> <p dir="auto">If you specify an environment variable value for <code>AWS_CF_DOMAIN</code> and <code>NODE_ENV=production</code> is set then your assets will need to be published to Amazon S3/Cloudfront. To do so run <code>npm start publish-assets</code> (or with yarn as <code>yarn start publish-assets</code>). This command automatically sets <code>NODE_ENV=production</code> for you as well via <code>cross-env</code>.</p> </li> </ol> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Provisioning</h4><a id="user-content-provisioning" class="anchor" aria-label="Permalink: Provisioning" href="#provisioning"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">See the <a href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/ansible">ansible</a> folder for our <a href="https://github.com/ansible/ansible">Ansible</a> configuration and playbooks, which we use to provision servers with.</p> <p dir="auto">We recommend you to install <a href="https://github.com/adrienverge/yamllint">yamllint</a> and configure it in your editor while working with <a href="https://github.com/ansible/ansible">Ansible</a> playbooks.</p> <p dir="auto">Also note that <a href="https://github.com/ansible/ansible-lint">ansible-lint</a> is a helpful linting tool you can use if you plan on making changes to playbooks. Note that our current playbooks have several existing lint errors.</p> <p dir="auto">First you must provision Ubuntu 18.04 LTS 64-bit server(s) using <a href="https://m.do.co/c/2ffb8129b8d6" rel="nofollow">Digital Ocean</a>, <a href="https://www.linode.com/?r=a2840b36770c7020730251a5643428ddbf2e284e" rel="nofollow">Linode</a>, <a href="https://www.vultr.com/?ref=7429848" rel="nofollow">Vultr</a>, or your host of choice. These newly provisioned server(s) should have your SSH key automatically added.</p> <p dir="auto">Follow the <a href="#deployment">Deployment</a> guide below for automatic provisioning and deployment instructions.</p> <div class="markdown-heading" dir="auto"><h5 tabindex="-1" class="heading-element" dir="auto">Deployment</h5><a id="user-content-deployment" class="anchor" aria-label="Permalink: Deployment" href="#deployment"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <ol dir="auto"> <li> <p dir="auto">Set up host configuration by copying the <code>hosts.yml</code> file template:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="cp ansible/playbooks/templates/hosts.yml hosts.yml"><pre>cp ansible/playbooks/templates/hosts.yml hosts.yml</pre></div> </li> <li> <p dir="auto">Edit this configuration and update the file with your newly created server aliases and IP addresses. You can add more than one host to each group if you are setting up load balancing. Refer to the <a href="#naming-convention">Naming Convention</a> documentation for our recommended approach to server alias naming. Note that this file is automatically ignored by git. If you have a private repository and would like to commit this, then remove <code>hosts.yml</code> from the root <code>.gitignore</code> file.</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="vim hosts.yml"><pre>vim hosts.yml</pre></div> </li> <li> <p dir="auto">Set up environment configuration by copying the <code>env</code> file template:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="cp ansible/playbooks/templates/env .env.production"><pre>cp ansible/playbooks/templates/env .env.production</pre></div> </li> <li> <p dir="auto">Edit this configuration and reference the official <a href="https://lad.js.org" rel="nofollow">Lad</a> documentation for a list of all available environment variables (or see <a href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/.env.defaults">.env.defaults</a>). <strong>You will need to open this file in your preferred editor</strong> and set the values for any fields containing <code>TODO</code>, whereby you replace <code>TODO</code> with the appropriate value. Preserve double quotes where they are already defined.</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="vim .env.production"><pre>vim .env.production</pre></div> </li> <li> <p dir="auto">Generate <a href="http://pm2.keymetrics.io/" rel="nofollow">pm2</a> <a href="https://pm2.keymetrics.io/docs/usage/application-declaration/" rel="nofollow">ecosystem files</a> using our automatic template generator. We created an <a href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/ansible-playbook.js">ansible-playbook.js</a> which loads the <code>.env.production</code> environment variables rendered with <a href="https://github.com/ladjs/env">@ladjs/env</a> into <code>process.env</code>, which then gets used in the playbooks. This is a superior, simple, and the only known dotenv approach we know of in Ansible. Newly created <code>ecosystem-api.json</code>, <code>ecosystem-bree.json</code>, <code>ecosystem-web.json</code> files will now be created for you in the root of the repository. If you ever more add or change IP addresses, you can simply re-run this command.</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="node ansible-playbook ansible/playbooks/ecosystem.yml -l 'localhost'"><pre>node ansible-playbook ansible/playbooks/ecosystem.yml -l <span class="pl-s"><span class="pl-pds">'</span>localhost<span class="pl-pds">'</span></span></pre></div> </li> <li> <p dir="auto">Set up the web and API server(s) (see <a href="https://docs.ansible.com/ansible/latest/user_guide/intro_patterns.html#patterns-and-ansible-playbook-flags" rel="nofollow">patterns and ansible-playbook flags docs</a> if you need help). If you completely (or partially) run this playbook (or any others below), then the second time you try to run it may not succeed. This is because we prevent root user access through security hardening. To workaround this, run the same command but without <code>-e 'ansible_user=root'</code> appended as it will default to the <code>devops</code> user created.</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="node ansible-playbook ansible/playbooks/http.yml -e 'ansible_user=root' -l 'http'"><pre>node ansible-playbook ansible/playbooks/http.yml -e <span class="pl-s"><span class="pl-pds">'</span>ansible_user=root<span class="pl-pds">'</span></span> -l <span class="pl-s"><span class="pl-pds">'</span>http<span class="pl-pds">'</span></span></pre></div> </li> <li> <p dir="auto">Set up the Bree server(s):</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="node ansible-playbook ansible/playbooks/bree.yml -e 'ansible_user=root' -l 'bree'"><pre>node ansible-playbook ansible/playbooks/bree.yml -e <span class="pl-s"><span class="pl-pds">'</span>ansible_user=root<span class="pl-pds">'</span></span> -l <span class="pl-s"><span class="pl-pds">'</span>bree<span class="pl-pds">'</span></span></pre></div> </li> <li> <p dir="auto">Set up the Redis server:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="node ansible-playbook ansible/playbooks/redis.yml -e 'ansible_user=root' -l 'redis'"><pre>node ansible-playbook ansible/playbooks/redis.yml -e <span class="pl-s"><span class="pl-pds">'</span>ansible_user=root<span class="pl-pds">'</span></span> -l <span class="pl-s"><span class="pl-pds">'</span>redis<span class="pl-pds">'</span></span></pre></div> </li> <li> <p dir="auto">Set up the Mongo server:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="node ansible-playbook ansible/playbooks/mongo.yml -e 'ansible_user=root' -l 'mongo'"><pre>node ansible-playbook ansible/playbooks/mongo.yml -e <span class="pl-s"><span class="pl-pds">'</span>ansible_user=root<span class="pl-pds">'</span></span> -l <span class="pl-s"><span class="pl-pds">'</span>mongo<span class="pl-pds">'</span></span></pre></div> </li> <li> <p dir="auto">Set up GitHub deployment keys for all the servers. Note that the <code>deployment-keys</code> directory is ignored from git, so if you have a private repository and wish to commit it, then remove <code>deployment-keys</code> from the <code>.gitignore</code> file.</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="node ansible-playbook ansible/playbooks/deployment-keys.yml -l 'http:bree'"><pre>node ansible-playbook ansible/playbooks/deployment-keys.yml -l <span class="pl-s"><span class="pl-pds">'</span>http:bree<span class="pl-pds">'</span></span></pre></div> </li> <li> <p dir="auto">Go to your repository "Settings" page on GitHub, click on "Deploy keys", and then add a deployment key for each servers' deployment key copied to the <code>deployment-keys</code> directory. If you're on macOS, you can use the <code>pbcopy</code> command to copy each file's contents to your clipboard. Use tab completion for speed, and replace the server names and paths with yours:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="cat deployment-keys/api-1-li-dal.forwardemail.net.pub | pbcopy # # NOTE: repeat the above command for all servers # and after running the command, it will copy # the key to your clipboard for you to paste as # a new deploy key (make sure to use read-only access) #"><pre>cat deployment-keys/api-1-li-dal.forwardemail.net.pub <span class="pl-k">|</span> pbcopy <span class="pl-c"><span class="pl-c">#</span></span> <span class="pl-c"><span class="pl-c">#</span> NOTE: repeat the above command for all servers</span> <span class="pl-c"><span class="pl-c">#</span> and after running the command, it will copy</span> <span class="pl-c"><span class="pl-c">#</span> the key to your clipboard for you to paste as</span> <span class="pl-c"><span class="pl-c">#</span> a new deploy key (make sure to use read-only access)</span> <span class="pl-c"><span class="pl-c">#</span></span></pre></div> </li> <li> <p dir="auto">Set up PM2 deployment directories on all the servers:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="pm2 deploy ecosystem-web.json production setup"><pre>pm2 deploy ecosystem-web.json production setup</pre></div> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="pm2 deploy ecosystem-api.json production setup"><pre>pm2 deploy ecosystem-api.json production setup</pre></div> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="pm2 deploy ecosystem-bree.json production setup"><pre>pm2 deploy ecosystem-bree.json production setup</pre></div> </li> <li> <p dir="auto">Create a SSL certificate at <a href="https://namecheap.com" rel="nofollow">Namecheap</a> (we recommend a 5 year wildcard certificate), set up the certificate, and download and extract the ZIP file with the certificate (emailed to you) to your computer. We do not recommend using tools like <a href="https://letsencrypt.org/" rel="nofollow">LetsEncrypt</a> and <code>certbot</code> due to complexity when you have (or scale to) a cluster of servers set up behind load balancers. In other words, we've tried approaches like <code>lsyncd</code> in combination with <code>crontab</code> for <code>certbot</code> renewals and automatic checking. Furthermore, using this exposes the server(s) to downtime as ports <code>80</code> and <code>443</code> may need to be shut down so that <code>certbot</code> can use them for certificate generation. This is not a reliable approach, and simply renewing certificates once a year is vastly simpler and also makes using load balancers trivial. Instead you can use a provider like <a href="https://namecheap.com" rel="nofollow">Namecheap</a> to get a cheap SSL certificate, then run a few commands as we've documented below. This command will prompt you for an absolute file path to the certificates you downloaded. Renewed your certificate after 1 year? Simply follow this step again. Do not set a password on the certificate files. When using the <code>openssl</code> command (see Namecheap instructions), you need to use <code>*.example.com</code> with an asterisk followed by a period if you are registering a wildcard certificate.</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="ansible-playbook ansible/playbooks/certificates.yml"><pre>ansible-playbook ansible/playbooks/certificates.yml</pre></div> <blockquote> <p dir="auto"><strong>Important:</strong> If you renew or change certificates in the future, then after running the previous command, you will subsequently need to reload the processes as such:</p> </blockquote> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# # NOTE: See the &quot;Important&quot; note above BEFORE running this command. # This command ONLY APPLIES for certificate renewals/changes. # pm2 deploy ecosystem-web.json production exec &quot;pm2 reload web&quot; pm2 deploy ecosystem-api.json production exec &quot;pm2 reload api&quot;"><pre><span class="pl-c"><span class="pl-c">#</span></span> <span class="pl-c"><span class="pl-c">#</span> NOTE: See the "Important" note above BEFORE running this command.</span> <span class="pl-c"><span class="pl-c">#</span> This command ONLY APPLIES for certificate renewals/changes.</span> <span class="pl-c"><span class="pl-c">#</span></span> pm2 deploy ecosystem-web.json production <span class="pl-c1">exec</span> <span class="pl-s"><span class="pl-pds">"</span>pm2 reload web<span class="pl-pds">"</span></span> pm2 deploy ecosystem-api.json production <span class="pl-c1">exec</span> <span class="pl-s"><span class="pl-pds">"</span>pm2 reload api<span class="pl-pds">"</span></span></pre></div> </li> <li> <p dir="auto">(Optional) Create a Google application credentials profile file and store it locally. You only need this if you want to support automatic translation. The following command will prompt you for the absolute file path (e.g. <code>/path/to/client-profile.json</code>). See the <a href="https://github.com/niftylettuce/mandarin">mandarin</a> docs for more information.</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="ansible-playbook ansible/playbooks/gapp-creds.yml -l 'http:bree'"><pre>ansible-playbook ansible/playbooks/gapp-creds.yml -l <span class="pl-s"><span class="pl-pds">'</span>http:bree<span class="pl-pds">'</span></span></pre></div> </li> <li> <p dir="auto">Copy the <code>.env.production</code> file and create an AWS config file on the servers:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="node ansible-playbook ansible/playbooks/env.yml -l 'http:bree'"><pre>node ansible-playbook ansible/playbooks/env.yml -l <span class="pl-s"><span class="pl-pds">'</span>http:bree<span class="pl-pds">'</span></span></pre></div> </li> <li> <p dir="auto">Run an initial deploy to all the servers:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="pm2 deploy ecosystem-web.json production"><pre>pm2 deploy ecosystem-web.json production</pre></div> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="pm2 deploy ecosystem-api.json production"><pre>pm2 deploy ecosystem-api.json production</pre></div> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="pm2 deploy ecosystem-bree.json production"><pre>pm2 deploy ecosystem-bree.json production</pre></div> </li> <li> <p dir="auto">Save the process list on the servers so when if the server were to reboot, it will automatically boot back up the processes:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="pm2 deploy ecosystem-web.json production exec &quot;pm2 save&quot;"><pre>pm2 deploy ecosystem-web.json production <span class="pl-c1">exec</span> <span class="pl-s"><span class="pl-pds">"</span>pm2 save<span class="pl-pds">"</span></span></pre></div> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="pm2 deploy ecosystem-api.json production exec &quot;pm2 save&quot;"><pre>pm2 deploy ecosystem-api.json production <span class="pl-c1">exec</span> <span class="pl-s"><span class="pl-pds">"</span>pm2 save<span class="pl-pds">"</span></span></pre></div> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="pm2 deploy ecosystem-bree.json production exec &quot;pm2 save&quot;"><pre>pm2 deploy ecosystem-bree.json production <span class="pl-c1">exec</span> <span class="pl-s"><span class="pl-pds">"</span>pm2 save<span class="pl-pds">"</span></span></pre></div> </li> <li> <p dir="auto">Test by visiting your web and API server in your browser (click "proceed to unsafe" site and bypass certificate warning).</p> </li> <li> <p dir="auto">Configure your DNS records for the web and API server hostnames and respective IP addresses.</p> </li> <li> <p dir="auto">Test by visiting your web and API server in your browser (in an incognito window). There should not be any certificate warnings (similar to the one that occurred in step 15).</p> </li> <li> <p dir="auto">(Optional) Remove the local <code>.env.production</code> file for security purposes. If you do this, then make sure you have a backup, or securely back up off the server in the future before destroying the server.</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="rm .env.production"><pre>rm .env.production</pre></div> </li> <li> <p dir="auto">(Optional) Remove the local certificate files you downloaded locally and specified in step 11. If you do this, then make sure you have a backup, or securely back up off the server in the future before destroying the server.</p> </li> <li> <p dir="auto">Finished. If you need to deploy again, then push your changes to GitHub <code>master</code> branch and then follow step 14 again. We recommend you to read the <a href="https://docs.ansible.com/ansible/latest/user_guide/intro_getting_started.html" rel="nofollow">Ansible getting started guide</a>, as it provides you with insight into commands like <code>ansible all -a "echo hello"</code> which can be run across all or specific servers.</p> </li> </ol> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Tests</h4><a id="user-content-tests" class="anchor" aria-label="Permalink: Tests" href="#tests"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">We use <a href="https://github.com/avajs/ava">ava</a> and <a href="https://github.com/istanbuljs/nyc">nyc</a> for testing and code coverage.</p> <p dir="auto"><a href="https://www.npmjs.com/" rel="nofollow">npm</a>:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="npm test"><pre>npm <span class="pl-c1">test</span></pre></div> <p dir="auto"><a href="https://yarnpkg.com/" rel="nofollow">yarn</a>:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="yarn test"><pre>yarn <span class="pl-c1">test</span></pre></div> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Configuration</h3><a id="user-content-configuration" class="anchor" aria-label="Permalink: Configuration" href="#configuration"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Environment Variables</h4><a id="user-content-environment-variables" class="anchor" aria-label="Permalink: Environment Variables" href="#environment-variables"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">We have made configuration of your Lad project easy through a <a href="https://github.com/motdotla/dotenv">dotenv</a> configuration package called <a href="https://github.com/ladjs/env">@ladjs/env</a>, per <a href="https://12factor.net/" rel="nofollow">Twelve-Factor</a>.</p> <p dir="auto">We use the following three packages to manage configuration:</p> <ul dir="auto"> <li><a href="https://github.com/niftylettuce/node-dotenv-extended">dotenv-extended</a> - allows us to craft a <code>.env</code> definition (otherwise known as a "schema") in a file named <code>.env.schema</code></li> <li><a href="https://github.com/janl/mustache.js/">mustache</a> - allows us to use the <a href="https://github.com/janl/mustache.js/">Mustache templating language</a> in our <code>.env</code> and <code>.env.defaults</code> configuration files</li> <li><a href="https://github.com/niftylettuce/dotenv-parse-variables">dotenv-parse-variables</a> - automatically parses variable types from <code>process.env</code> (e.g. <code>FOO=4</code> will set <code>process.env.FOO = 4</code> with a <code>Number</code> variable type instead of a <code>String</code>)</li> </ul> <p dir="auto">Configuration is managed by the following, in order of priority:</p> <ol dir="auto"> <li>Contents of the file at <code>config/index.js</code> (reads in <code>process.env</code> environment variables)</li> <li>Contents of the files in directories under <code>config/environments/</code> (sets defaults per environment, e.g. you can pass <code>NODE_ENV=staging</code> and it will load the file at <code>config/environments/staging.js</code>)</li> <li>Environment variables used to override defaults or set required ones (e.g. <code>NODE_ENV=production</code>)</li> <li>Environment configuration in <code>.env</code></li> <li>Environment configuration in <code>.env.defaults</code></li> </ol> <p dir="auto">Precedence is taken by the environment configuration files, environment variables, then the <code>.env</code> file.</p> <p dir="auto">Basically <a href="https://github.com/motdotla/dotenv">dotenv</a> won't set an environment variable if it already detects it was passed as an environment variable.</p> <p dir="auto">Take a look at the <a href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/config">config</a> folder contents and also at the defaults at <a href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/.env.defaults">.env.defaults</a>.</p> <ul dir="auto"> <li><code>NODE_ENV</code> - (options: <code>development</code>, <code>production</code> default: <code>development</code>) - the node environment the app is running in</li> <li><code>PROXY_PORT</code> - (default: <code>8080</code>) - proxy port used to proxy requests (see <a href="https://github.com/ladjs/proxy">ladjs/proxy</a>)</li> <li><code>HTTP_PROTOCOL</code> - (defaults: <code>http</code> recommend: <code>https</code>) - protocol used for http requests</li> <li><code>HTTP_PORT</code> - (defaults: <code>80</code> recommend: <code>443</code>) - http port used for http requests</li> <li><code>WEB_PROTOCOL</code> - (default: <code>http</code>) - <a href="https://github.com/ladjs/web">ladjs/web</a> application protocol</li> <li><code>WEB_HOST</code> - (default: <code>localhost</code>) - <a href="https://github.com/ladjs/web">ladjs/web</a> application host</li> <li><code>WEB_PORT</code> - (default: <code>3000</code>) - <a href="https://github.com/ladjs/web">ladjs/web</a> application port</li> <li><code>WEB_URL</code> - (default: <code>{{WEB_PROTOCOL}}://{{WEB_HOST}}:{{WEB_PORT}}</code>) - web application absolute URI</li> <li><code>WEB_SSL_KEY_PATH</code> - <a href="https://github.com/ladjs/web">ladjs/web</a> file path to your SSL key file</li> <li><code>WEB_SSL_CERT_PATH</code> - <a href="https://github.com/ladjs/web">ladjs/web</a> file path to your SSL certificate file</li> <li><code>WEB_SSL_CA_PATH</code> - <a href="https://github.com/ladjs/web">ladjs/web</a> file path to your SSL certificate authority file</li> <li><code>API_HOST</code> - (default: <code>localhost</code>) - <a href="https://github.com/ladjs/api">ladjs/api</a> host</li> <li><code>API_PORT</code> - (default: <code>4000</code>) - <a href="https://github.com/ladjs/api">ladjs/api</a> port</li> <li><code>API_PROTOCOL</code> - (default: <code>http</code> recommend: <code>https</code>) - <a href="https://github.com/ladjs/api">ladjs/api</a> protocol</li> <li><code>API_URL</code> - (default: <code>{{API_PROTOCOL}}://{{API_HOST}}:{{API_PORT}}</code>) - <a href="https://github.com/ladjs/api">ladjs/api</a> absolute URI</li> <li><code>API_SSL_KEY_PATH</code> - <a href="https://github.com/ladjs/api">ladjs/api</a> file path to your SSL key file</li> <li><code>API_SSL_CERT_PATH</code> - <a href="https://github.com/ladjs/api">ladjs/api</a> file path to your SSL certificate file</li> <li><code>API_SSL_CA_PATH</code> - <a href="https://github.com/ladjs/api">ladjs/api</a> file path to your SSL certificate authority file</li> <li><code>API_RATELIMIT_WHITELIST</code> - <a href="https://github.com/ladjs/api">ladjs/api</a> ratelimiter whitelisted ips (see: <a href="https://github.com/scttcper/koa-simple-ratelimit">koa-simple-ratelimit</a>)</li> <li><code>APP_NAME</code> - (default: <code>Lad</code>) - application name (see <a href="https://github.com/search?p=3&amp;q=org%3Aladjs+appName&amp;type=Code">usage</a>)</li> <li><code>APP_COLOR</code> - application color theme (see <a href="https://github.com/search?q=org%3Aladjs+appColor&amp;type=Code">usage</a>)</li> <li><code>TWITTER</code> - (default: <code>@niftylettuce</code>) twitter handle</li> <li><code>SEND_EMAIL</code> - (default: <code>false</code>) - whether to send email or preview (see <a href="https://github.com/ladjs/lad#outbound-email-configuration">outbound email configuration</a>)</li> <li><code>TRANSPORT_DEBUG</code> - (default: <code>false</code>) - email transport debug logging (see <a href="https://github.com/ladjs/lad#debugging">debugging</a>)</li> <li><code>EMAIL_DEFAULT_FROM</code> - (default: <code>support@127.0.01</code>) - default email <code>from</code> address</li> <li><code>SHOW_STACK</code> - (default: <code>true</code>) - whether or not to output a stack trace when logging (see <a href="https://github.com/cabinjs/axe#options">cabinjs options</a>)</li> <li><code>SHOW_META</code> - (default: <code>true</code>) - whether or not to output metadata to logger methods (see <a href="https://github.com/cabinjs/axe#options">cabinjs options</a>)</li> <li><code>SUPPORT_REQUEST_MAX_LENGTH</code> - (default: <code>500</code>) - support request max message size in characters</li> <li><code>ERROR_HANDLER_BASE_URL</code> - (default: <code>{{WEB_URL}}</code>) error handling base url (see <a href="https://github.com/ladjs/koa-better-error-handler">koa-better-error-handler</a>)</li> <li><code>I18N_SYNC_FILES</code> - (default: <code>true</code>) - sync locale information across all files (see <a href="https://github.com/ladjs/i18n#options">ladjs/i18n options</a>)</li> <li><code>I18N_AUTO_RELOAD</code> - (default: <code>false</code>) - watch for changes in json files to reload locale on updates (see <a href="https://github.com/ladjs/i18n#options">ladjs/i18n options</a>)</li> <li><code>I18N_UPDATE_FILES</code> - (default: <code>true</code>) - write new locale information to disk (see <a href="https://github.com/ladjs/i18n#options">ladjs/i18n options</a>)</li> <li><code>AUTH_LOCAL_ENABLED</code> - (default: <code>true</code>) - enable passport local strategy (see <a href="https://github.com/ladjs/passport">ladjs/passport</a>)</li> <li><code>AUTH_FACEBOOK_ENABLED</code> - (default: <code>false</code>) - enable authenticating with Facebook using the OAuth 2.0 (see <a href="https://github.com/ladjs/passport">ladjs/passport</a>)</li> <li><code>AUTH_TWITTER_ENABLED</code> - (default: <code>false</code>) - enable authenticating with Twitter using the OAuth 1.0 (see <a href="https://github.com/ladjs/passport">ladjs/passport</a>)</li> <li><code>AUTH_GOOGLE_ENABLED</code> - (default: <code>false</code>) - enable authenticating with Google using OAuth 2.0 (see <a href="https://github.com/ladjs/lad#google-auth">google auth</a>)</li> <li><code>AUTH_GITHUB_ENABLED</code> - (default: <code>false</code>) - enable authenticating with Github using OAuth 2.0 (see <a href="https://github.com/ladjs/passport">ladjs/passport</a>)</li> <li><code>AUTH_LINKEDIN_ENABLED</code> - (default: <code>false</code>) - enable authenticating with LinkedIn using OAuth 1.0 (see <a href="https://github.com/ladjs/passport">ladjs/passport</a>)</li> <li><code>AUTH_INSTAGRAM_ENABLED</code> - (default: <code>false</code>) - enable authenticating with Instagram using OAuth 2.0 (see <a href="https://github.com/ladjs/passport">ladjs/passport</a>)</li> <li><code>AUTH_OTP_ENABLED</code> - (default: <code>false</code>) - enable authenticating with OTP, a form of two-factor authentication (see <a href="https://github.com/ladjs/passport">ladjs/passport</a>)</li> <li><code>AUTH_STRIPE_ENABLED</code> - (default: false) - enable authenticating with Stripe using OAuth 2.0 (see <a href="https://github.com/ladjs/passport">ladjs/passport</a>)</li> <li><code>GOOGLE_CLIENT_ID</code> - google oauth2 client id (see <a href="https://github.com/ladjs/lad#google-auth">google auth</a>)</li> <li><code>GOOGLE_CLIENT_SECRET</code> - google oauth2 secret (see <a href="https://github.com/ladjs/lad#google-auth">google auth</a>)</li> <li><code>GOOGLE_CALLBACK_URL</code> - google oauth2 callback url (see <a href="https://github.com/ladjs/lad#google-auth">google auth</a>)</li> <li><code>GOOGLE_APPLICATION_CREDENTIALS</code> - path to google cloud platform credentials (see <a href="https://cloud.google.com/docs/authentication/getting-started" rel="nofollow">gcp credentials</a>)</li> <li><code>GITHUB_CLIENT_ID</code> - github oauth client id (see <a href="https://github.com/ladjs/passport">ladjs/passport</a>)</li> <li><code>GITHUB_CLIENT_SECRET</code> - github oauth secret (see <a href="https://github.com/ladjs/passport">ladjs/passport</a>)</li> <li><code>GITHUB_CALLBACK_URL</code> - github oauth callback URL (see <a href="https://github.com/ladjs/passport">ladjs/passport</a>)</li> <li><code>POSTMARK_API_TOKEN</code> - postmark api token (see <a href="https://github.com/ladjs/lad#outbound-email-configuration">outbound email configuration</a>)</li> <li><code>CODECOV_TOKEN</code> - codecov api token (see <a href="https://github.com/ladjs/lad#continuous-integration-and-code-coverage">continuous integration and code coverage</a>)</li> <li><code>MONGO_USER</code> - mongodb username</li> <li><code>MONGO_PASS</code> - mongodb password</li> <li><code>MONGO_HOST</code> - (default: <code>localhost</code>) - mongodb hostname</li> <li><code>MONGO_PORT</code> - (default: <code>27017</code>) - mongodb port</li> <li><code>MONGO_NAME</code> - (default: <code>{{APP_NAME}}_{{NODE_ENV}}</code>) - mongodb name</li> <li><code>MONGO_URI</code> - (default: <code>mongodb://{{MONGO_HOST}}:{{MONGO_PORT}}/{{MONGO_NAME}}</code>) - mongodb connection URI</li> <li><code>WEB_MONGO_USER</code> - <a href="https://github.com/ladjs/web">ladjs/web</a> mongodb username</li> <li><code>WEB_MONGO_PASS</code> - <a href="https://github.com/ladjs/web">ladjs/web</a> mongodb password</li> <li><code>WEB_MONGO_HOST</code> - <a href="https://github.com/ladjs/web">ladjs/web</a> mongodb hostname</li> <li><code>WEB_MONGO_NAME</code> - <a href="https://github.com/ladjs/web">ladjs/web</a> mongodb name</li> <li><code>WEB_MONGO_PORT</code> - <a href="https://github.com/ladjs/web">ladjs/web</a> mongodb port</li> <li><code>WEB_MONGO_URI</code> - <a href="https://github.com/ladjs/web">ladjs/web</a> mongodb connection URI</li> <li><code>API_MONGO_USER</code> - <a href="https://github.com/ladjs/api">ladjs/api</a> mongodb username</li> <li><code>API_MONGO_PASS</code> - <a href="https://github.com/ladjs/api">ladjs/api</a> mongodb password</li> <li><code>API_MONGO_HOST</code> - <a href="https://github.com/ladjs/api">ladjs/api</a> mongodb hostname</li> <li><code>API_MONGO_NAME</code> - <a href="https://github.com/ladjs/api">ladjs/api</a> mongodb name</li> <li><code>API_MONGO_PORT</code> - <a href="https://github.com/ladjs/api">ladjs/api</a> mongodb port</li> <li><code>API_MONGO_URI</code> - <a href="https://github.com/ladjs/api">ladjs/api</a> mongodb connection URI</li> <li><code>BREE_MONGO_USER</code> - <a href="https://github.com/breejs/bree">breejs/bree</a> mongodb username</li> <li><code>BREE_MONGO_PASS</code> - <a href="https://github.com/breejs/bree">breejs/bree</a> mongodb password</li> <li><code>BREE_MONGO_HOST</code> - <a href="https://github.com/breejs/bree">breejs/bree</a> mongodb hostname</li> <li><code>BREE_MONGO_NAME</code> - <a href="https://github.com/breejs/bree">breejs/bree</a> mongodb name</li> <li><code>BREE_MONGO_PORT</code> - <a href="https://github.com/breejs/bree">breejs/bree</a> mongodb port</li> <li><code>BREE_MONGO_URI</code> - <a href="https://github.com/breejs/bree">breejs/bree</a> mongodb connection URI</li> <li><code>REDIS_PORT</code> - (default: <code>6379</code>) - redis port</li> <li><code>REDIS_HOST</code> - (default: <code>localhost</code>) - redis hostname</li> <li><code>REDIS_PASSWORD</code> - redis password</li> <li><code>WEB_REDIS_PORT</code> - <a href="https://github.com/ladjs/web">ladjs/web</a> redis port</li> <li><code>WEB_REDIS_HOST</code> - <a href="https://github.com/ladjs/web">ladjs/web</a> redis hostname</li> <li><code>WEB_REDIS_PASSWORD</code> - <a href="https://github.com/ladjs/web">ladjs/web</a> redis password</li> <li><code>API_REDIS_PORT</code> - <a href="https://github.com/ladjs/api">ladjs/api</a> redis port</li> <li><code>API_REDIS_HOST</code> - <a href="https://github.com/ladjs/api">ladjs/api</a> redis hostname</li> <li><code>API_REDIS_PASSWORD</code> - <a href="https://github.com/ladjs/api">ladjs/api</a> redis password</li> <li><code>BREE_REDIS_PORT</code> - <a href="https://github.com/breejs/bree">breejs/bree</a> redis port</li> <li><code>BREE_REDIS_HOST</code> - <a href="https://github.com/breejs/bree">breejs/bree</a> redis hostname</li> <li><code>BREE_REDIS_PASSWORD</code> - <a href="https://github.com/breejs/bree">breejs/bree</a> redis password</li> <li><code>MANDARIN_REDIS_PORT</code> - <a href="https://github.com/niftylettuce/mandarin">mandarin</a> redis port</li> <li><code>MANDARIN_REDIS_HOST</code> - <a href="https://github.com/niftylettuce/mandarin">mandarin</a> redis hostname</li> <li><code>MANDARIN_REDIS_PASSWORD</code> - <a href="https://github.com/niftylettuce/mandarin">mandarin</a> redis password</li> <li><code>CERTBOT_WELL_KNOWN_NAME</code> - letsencrypt wellknown name (see <a href="https://certbot.eff.org/docs/using.html#id11" rel="nofollow">certbot options</a>)</li> <li><code>CERTBOT_WELL_KNOWN_CONTENTS</code> - letsencrypt wellknown contents (see <a href="https://certbot.eff.org/docs/using.html#id11" rel="nofollow">certbot options</a>)</li> <li><code>VERIFICATION_PIN_TIMEOUT_MS</code> - (default: <code>5m</code>) - email verification pin expiry</li> <li><code>VERIFICATION_PIN_EMAIL_INTERVAL_MS</code> - (default: <code>1m</code>) - email verification pin email interval</li> <li><code>API_SECRETS</code> - (default: <code>secret</code>) - list of restricted api secrets</li> <li><code>CACHE_RESPONSES</code> - (default: <code>false</code>) - cache specified responses (see <a href="https://github.com/ladjs/koa-cache-responses">ladjs/koa-cache-responses</a>)</li> <li><code>SLACK_API_TOKEN</code> - slack api token (see <a href="https://slack.dev/node-slack-sdk/web-api" rel="nofollow">slack web api</a>)</li> </ul> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">SSL Configuration</h4><a id="user-content-ssl-configuration" class="anchor" aria-label="Permalink: SSL Configuration" href="#ssl-configuration"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">To configure SSL for the web or API server simply set them in your <code>.env</code> file or pass them as environment variables.</p> <blockquote> <p dir="auto">Web server:</p> </blockquote> <ul dir="auto"> <li><code>WEB_PROTOCOL</code> - you must set this to <code>https</code></li> <li><code>WEB_SSL_KEY_PATH</code> - file path to your SSL key file (e.g. <code>/home/deploy/.ssl/web-key.pem</code>)</li> <li><code>WEB_SSL_CERT_PATH</code> - file path to your SSL certificate file (e.g. <code>/home/deploy/.ssl/web-cert.pem</code>)</li> <li><code>WEB_SSL_CA_PATH</code> (optional) - file path to your SSL certificate authority file (e.g. <code>/home/deploy/.ssl/web-ca-cert.pem</code>)</li> </ul> <blockquote> <p dir="auto">API server:</p> </blockquote> <ul dir="auto"> <li><code>API_PROTOCOL</code> - you must set this to <code>https</code></li> <li><code>API_SSL_KEY_PATH</code> - file path to your SSL key file (e.g. <code>/home/deploy/.ssl/api-key.pem</code>)</li> <li><code>API_SSL_CERT_PATH</code> - file path to your SSL certificate file (e.g. <code>/home/deploy/.ssl/api-cert.pem</code>)</li> <li><code>API_SSL_CA_PATH</code> (optional) - file path to your SSL certificate authority file (e.g. <code>/home/deploy/.ssl/api-ca-cert.pem</code>)</li> </ul> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Outbound Email Configuration</h4><a id="user-content-outbound-email-configuration" class="anchor" aria-label="Permalink: Outbound Email Configuration" href="#outbound-email-configuration"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">By default in the development environment we simply render the email in your browser.</p> <p dir="auto">However in other environments such as production, you definitely want emails to be sent.</p> <p dir="auto">We built-in support for Postmark by default (though you can swap in your own <code>transport</code> provider in the <code>jobs/email.js</code> file):</p> <ol dir="auto"> <li> <p dir="auto">Go to <a href="https://postmarkapp.com?utm_source=lad" rel="nofollow">https://postmarkapp.com</a> – Start Free Trial</p> </li> <li> <p dir="auto">Create a free trial account, then click Get Started, and proceed to create a "Server" and "Sender Signature"</p> </li> <li> <p dir="auto">Copy/paste the "Server API token" under "Credentials" in your <code>.env</code> file (example below)</p> <div class="highlight highlight-source-diff notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="-POSTMARK_API_TOKEN= +POSTMARK_API_TOKEN=ac6657eb-2732-4cfd-915b-912b1b10beb1"><pre><span class="pl-md"><span class="pl-md">-</span>POSTMARK_API_TOKEN=</span> <span class="pl-mi1"><span class="pl-mi1">+</span>POSTMARK_API_TOKEN=ac6657eb-2732-4cfd-915b-912b1b10beb1</span></pre></div> </li> <li> <p dir="auto">Modify the <code>SEND_EMAIL</code> variable in <code>.env</code> from <code>false</code> to <code>true</code></p> </li> </ol> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Favicon and Touch Icon Configuration</h4><a id="user-content-favicon-and-touch-icon-configuration" class="anchor" aria-label="Permalink: Favicon and Touch Icon Configuration" href="#favicon-and-touch-icon-configuration"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">You can customize the favicon and touch icons – just generate a new set at <a href="https://realfavicongenerator.net" rel="nofollow">https://realfavicongenerator.net</a> and overwrite the existing in the <a href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/template/assets">assets</a> folder.</p> <p dir="auto">Just make sure that any relative paths match up in the <code>assets/browserconfig.xml</code> and <code>assets/manifest.json</code> files.</p> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Authentication Methods</h4><a id="user-content-authentication-methods" class="anchor" aria-label="Permalink: Authentication Methods" href="#authentication-methods"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">We use Lad's auth package under the hood; so if you want to configure authentication providers you'll want to read more or contribute to <a href="https://github.com/ladjs/auth">@ladjs/auth</a>.</p> <div class="markdown-heading" dir="auto"><h5 tabindex="-1" class="heading-element" dir="auto">Google Auth</h5><a id="user-content-google-auth" class="anchor" aria-label="Permalink: Google Auth" href="#google-auth"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">In order to add Google sign-in to your app (so users can log in with their Google account):</p> <ol dir="auto"> <li> <p dir="auto">Go to <a href="https://console.developers.google.com" rel="nofollow">https://console.developers.google.com</a> – Create a project (and fill out your project information – if you need a 120x120px default image, <a href="https://cdn.rawgit.com/ladjs/lad/82d38d64/media/lad-120x120.png" rel="nofollow">you can use this one</a> with a CDN path of <a href="https://cdn.rawgit.com/ladjs/lad/82d38d64/media/lad-120x120.png" rel="nofollow">https://cdn.rawgit.com/ladjs/lad/82d38d64/media/lad-120x120.png</a></p> </li> <li> <p dir="auto">Under your newly created project, go to Credentials – Create credentials – OAuth client ID – Web application</p> </li> <li> <p dir="auto">Set "Authorized JavaScript origins" to <code>http://yourdomain.com</code> (replace with your domain) and also <code>http://localhost:3000</code> (for local development)</p> </li> <li> <p dir="auto">Set "Authorized redirect URIs" to <code>http://yourdomain.com/auth/google/ok</code> (again, replace with your domain) and also <code>http://localhost:3000/auth/google/ok</code> (again, for local development)</p> </li> <li> <p dir="auto">Copy and paste the newly created key pair for respective properties in your <code>.env</code> file (example below)</p> <div class="highlight highlight-source-diff notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="-GOOGLE_CLIENT_ID= +GOOGLE_CLIENT_ID=424623312719-73vn8vb4tmh8nht96q7vdbn3mc9pd63a.apps.googleusercontent.com -GOOGLE_CLIENT_SECRET= +GOOGLE_CLIENT_SECRET=Oys6WrHleTOksqXTbEY_yi07"><pre><span class="pl-md"><span class="pl-md">-</span>GOOGLE_CLIENT_ID=</span> <span class="pl-mi1"><span class="pl-mi1">+</span>GOOGLE_CLIENT_ID=424623312719-73vn8vb4tmh8nht96q7vdbn3mc9pd63a.apps.googleusercontent.com</span> <span class="pl-md"><span class="pl-md">-</span>GOOGLE_CLIENT_SECRET=</span> <span class="pl-mi1"><span class="pl-mi1">+</span>GOOGLE_CLIENT_SECRET=Oys6WrHleTOksqXTbEY_yi07</span></pre></div> </li> <li> <p dir="auto">In <code>.env</code>, make sure that <code>AUTH_GOOGLE_ENABLED=true</code> to enable this authentication method.</p> </li> </ol> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Translation Configuration</h4><a id="user-content-translation-configuration" class="anchor" aria-label="Permalink: Translation Configuration" href="#translation-configuration"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <ol dir="auto"> <li>Go to <a href="https://console.developers.google.com" rel="nofollow">https://console.developers.google.com</a></li> <li>Enable the Google Translate API</li> <li>Copy your API key and set it as the environment variable <code>GOOGLE_TRANSLATE_KEY=******</code></li> </ol> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Continuous Integration and Code Coverage</h4><a id="user-content-continuous-integration-and-code-coverage" class="anchor" aria-label="Permalink: Continuous Integration and Code Coverage" href="#continuous-integration-and-code-coverage"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">We strongly recommend that you use <a href="https://semaphoreci.com/?ref=lad" rel="nofollow">SemaphoreCI</a> for continuous integration and <a href="https://codecov.io/gh" rel="nofollow">Codecov</a> for code coverage.</p> <p dir="auto">Here are the simple steps required to setup <a href="https://semaphoreci.com/?ref=lad" rel="nofollow">SemaphoreCI</a> with <a href="https://codecov.io/gh" rel="nofollow">Codecov</a>:</p> <ol dir="auto"> <li> <p dir="auto">Go to <a href="https://semaphoreci.com/?ref=lad" rel="nofollow">SemaphoreCI</a> and sign up for a free account</p> </li> <li> <p dir="auto">Once your repository is pushed to GitHub, add it as a project on SemaphoreCI</p> </li> <li> <p dir="auto">Configure your project on SemaphoreCI with the following build settings:</p> <blockquote> <p dir="auto">Replace <code>npm</code> with <code>yarn</code> if you're using <a href="https://yarnpkg.com/" rel="nofollow">yarn</a> as your package manager</p> </blockquote> <ul dir="auto"> <li>Language: <code>JavaScript</code></li> <li>Node.js version: <code>10+</code> (latest LTS) <blockquote> <p dir="auto">Note you can also add to <code>Setup</code> the script <code>nvm install latest</code> to install latest version if SemaphoreCI does not provide it from the drop-down</p> </blockquote> </li> <li>Setup: <code>npm install</code></li> <li>Job 1: <code>npm run test-coverage</code></li> <li>After job: <code>npm run coverage</code></li> </ul> </li> <li> <p dir="auto">Go to <a href="https://codecov.io/gh" rel="nofollow">Codecov</a> and sign up for a free account</p> </li> <li> <p dir="auto">Add your project on Codecov and copy to your clipboard the token</p> </li> <li> <p dir="auto">Go to SemaphoreCI's Project Settings for your project and add <code>CODECOV_TOKEN</code> as an environment variable (with the contents from your clipboard)</p> </li> <li> <p dir="auto">Run a test build ("Rebuild last revision") on SemaphoreCI and check to make sure your code coverage report uploads properly on Codecov</p> </li> <li> <p dir="auto">Ensure your <code>README.md</code> file has the build status and code coverage badges rendered properly (you will need to use a different badge link from each provider if your GitHub repository is private)</p> </li> </ol> <div class="markdown-heading" dir="auto"><h4 tabindex="-1" class="heading-element" dir="auto">Amazon S3 and CloudFront Asset Setup</h4><a id="user-content-amazon-s3-and-cloudfront-asset-setup" class="anchor" aria-label="Permalink: Amazon S3 and CloudFront Asset Setup" href="#amazon-s3-and-cloudfront-asset-setup"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">In order for your assets to get properly served in a production environment, you'll need to configure AWS:</p> <ol dir="auto"> <li> <p dir="auto">Go to <a href="https://console.aws.amazon.com/iam/home#security_credential" rel="nofollow">https://console.aws.amazon.com/iam/home#security_credential</a> ‐ Access Keys – Create New Access Key</p> </li> <li> <p dir="auto">Copy and paste the newly created key pair for respective properties in your <code>.env</code> file (example below)</p> <div class="highlight highlight-source-diff notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="-AWS_IAM_KEY= +AWS_IAM_KEY=AKIAJMH22P6W674YFC7Q -AWS_IAM_SECRET= +AWS_IAM_SECRET=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"><pre><span class="pl-md"><span class="pl-md">-</span>AWS_IAM_KEY=</span> <span class="pl-mi1"><span class="pl-mi1">+</span>AWS_IAM_KEY=AKIAJMH22P6W674YFC7Q</span> <span class="pl-md"><span class="pl-md">-</span>AWS_IAM_SECRET=</span> <span class="pl-mi1"><span class="pl-mi1">+</span>AWS_IAM_SECRET=9MpR1FOXwPEtPlrlU5WbHjnz2KDcKWSUcB+C5CpS</span></pre></div> </li> <li> <p dir="auto">Enable your API by clicking on Overview and then clicking the Enable button</p> </li> <li> <p dir="auto">Go to <a href="https://console.aws.amazon.com/s3/home" rel="nofollow">https://console.aws.amazon.com/s3/home</a> – Create Bucket</p> </li> <li> <p dir="auto">Create a bucket and copy/paste its name for the property in <code>.env</code> (example below)</p> <div class="highlight highlight-source-diff notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="-AWS_S3_BUCKET= +AWS_S3_BUCKET=lad-development"><pre><span class="pl-md"><span class="pl-md">-</span>AWS_S3_BUCKET=</span> <span class="pl-mi1"><span class="pl-mi1">+</span>AWS_S3_BUCKET=lad-development</span></pre></div> </li> <li> <p dir="auto">Go to <a href="https://console.aws.amazon.com/cloudfront/home" rel="nofollow">https://console.aws.amazon.com/cloudfront/home</a> – Create Distribution – Get Started</p> </li> <li> <p dir="auto">Set "Origin Domain Name" equal to your S3 bucket name (their autocomplete drop-down will help you find it)</p> </li> <li> <p dir="auto">Leave the remaining defaults as is (some fields might be blank, this is OK)</p> </li> <li> <p dir="auto">Copy/paste the newly created Distribution ID and Domain Name for respective properties in your <code>.env</code> file (example below)</p> <div class="highlight highlight-source-diff notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="-AWS_CF_DI= +AWS_CF_DI=E2IBEULE9QOPVE -AWS_CF_DOMAIN= +AWS_CF_DOMAIN=d36aditw73gdrz.cloudfront.net"><pre><span class="pl-md"><span class="pl-md">-</span>AWS_CF_DI=</span> <span class="pl-mi1"><span class="pl-mi1">+</span>AWS_CF_DI=E2IBEULE9QOPVE</span> <span class="pl-md"><span class="pl-md">-</span>AWS_CF_DOMAIN=</span> <span class="pl-mi1"><span class="pl-mi1">+</span>AWS_CF_DOMAIN=d36aditw73gdrz.cloudfront.net</span></pre></div> </li> </ol> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Tutorials</h3><a id="user-content-tutorials" class="anchor" aria-label="Permalink: Tutorials" href="#tutorials"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <ul dir="auto"> <li><a href="https://github.com/koajs/koa#getting-started">Writing Your App</a></li> <li><a href="http://niftylettuce.com/posts/automated-node-app-ci-graceful-zerodowntime-github-pm2/" rel="nofollow">Continous Integration and Deployment</a></li> </ul> <div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Community</h3><a id="user-content-community" class="anchor" aria-label="Permalink: Community" href="#community"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <ul dir="auto"> <li><a href="https://twitter.com/niftylettuce" rel="nofollow">Follow us on Twitter</a></li> <li><a href="https://join.slack.com/t/ladjs/shared_invite/zt-fqei6z11-Bq2trhwHQxVc5x~ifiZG0g/" rel="nofollow">Join our Slack channel</a></li> <li><a href="https://www.twitch.tv/niftylettuce" rel="nofollow">Subscribe to our Twitch channel</a></li> <li><a href="https://github.com/koajs/koa#community">Visit Koa's Community section</a>.</li> <li><a href="http://slack.mongoosejs.io/" rel="nofollow">Join Mongoose's Slack channel</a></li> </ul> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Architecture</h2><a id="user-content-architecture" class="anchor" aria-label="Permalink: Architecture" href="#architecture"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">The following bash output is the directory structure and organization of Lad:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="tree template -I &quot;build|node_modules|coverage|test&quot;"><pre>tree template -I <span class="pl-s"><span class="pl-pds">"</span>build|node_modules|coverage|test<span class="pl-pds">"</span></span></pre></div> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="template ├── LICENSE ├── README ├── ansible │   ├── playbooks │   │   ├── aws-credentials.yml │   │   ├── bree.yml │   │   ├── certificates.yml │   │   ├── deployment-keys.yml │   │   ├── ecosystem.yml │   │   ├── env.yml │   │   ├── gapp-creds.yml │   │   ├── http.yml │   │   ├── mongo.yml │   │   ├── node.yml │   │   ├── python.yml │   │   ├── redis.yml │   │   ├── security.yml │   │   ├── ssh-keys.yml │   │   └── templates │   │   ├── aws-credentials.j2 │   │   ├── before.rules.j2 │   │   ├── ecosystem-api.json.j2 │   │   ├── ecosystem-bree.json.j2 │   │   ├── ecosystem-web.json.j2 │   │   ├── env │   │   ├── hosts.yml │   │   └── security-limits.d-mongod.conf │   └── requirements.yml ├── ansible-playbook.js ├── ansible.cfg ├── api.js ├── app │   ├── controllers │   │   ├── api │   │   │   ├── index.js │   │   │   └── v1 │   │   │   ├── index.js │   │   │   ├── log.js │   │   │   └── users.js │   │   ├── index.js │   │   └── web │   │   ├── admin │   │   │   ├── index.js │   │   │   └── users.js │   │   ├── auth.js │   │   ├── index.js │   │   ├── my-account.js │   │   ├── otp │   │   │   ├── disable.js │   │   │   ├── index.js │   │   │   ├── keys.js │   │   │   ├── recovery.js │   │   │   └── setup.js │   │   ├── report.js │   │   └── support.js │   ├── models │   │   ├── index.js │   │   ├── inquiry.js │   │   └── user.js │   └── views │   ├── 404.pug │   ├── 500.pug │   ├── _breadcrumbs.pug │   ├── _footer.pug │   ├── _nav.pug │   ├── _pagination.pug │   ├── _register-or-login.pug │   ├── about.pug │   ├── admin │   │   ├── index.pug │   │   └── users │   │   ├── index.pug │   │   └── retrieve.pug │   ├── change-email.pug │   ├── dashboard │   │   └── index.pug │   ├── donate.pug │   ├── forgot-password.pug │   ├── home.pug │   ├── layout.pug │   ├── my-account │   │   ├── index.pug │   │   ├── profile.pug │   │   └── security.pug │   ├── otp │   │   ├── enable.pug │   │   ├── keys.pug │   │   ├── login.pug │   │   └── setup.pug │   ├── privacy.pug │   ├── register-or-login.pug │   ├── reset-password.pug │   ├── spinner │   │   ├── 1.pug │   │   ├── 10.pug │   │   ├── 11.pug │   │   ├── 2.pug │   │   ├── 3.pug │   │   ├── 4.pug │   │   ├── 5.pug │   │   ├── 6.pug │   │   ├── 7.pug │   │   ├── 8.pug │   │   ├── 9.pug │   │   └── spinner.pug │   ├── support.pug │   ├── terms.pug │   └── verify.pug ├── assets │   ├── browserconfig.xml │   ├── css │   │   ├── _btn-auth.scss │   │   ├── _custom.scss │   │   ├── _email.scss │   │   ├── _markdown.scss │   │   ├── _responsive-backgrounds.scss │   │   ├── _responsive-borders.scss │   │   ├── _responsive-rounded.scss │   │   ├── _swal2.scss │   │   ├── _variables.scss │   │   └── app.scss │   ├── fonts │   ├── img │   │   ├── android-chrome-192x192.png │   │   ├── android-chrome-384x384.png │   │   ├── apple-touch-icon.png │   │   ├── favicon-16x16.png │   │   ├── favicon-32x32.png │   │   ├── favicon.ico │   │   ├── github-logo.svg │   │   ├── google-logo.svg │   │   ├── logo-square.svg │   │   ├── mstile-150x150.png │   │   ├── social.png │   │   └── twitter.png │   ├── js │   │   ├── core.js │   │   ├── logger.js │   │   └── uncaught.js │   ├── robots.txt │   └── site.webmanifest ├── bree.js ├── config │   ├── api.js │   ├── bree.js │   ├── cookies.js │   ├── env.js │   ├── filters.js │   ├── i18n.js │   ├── index.js │   ├── koa-cash.js │   ├── locales.js │   ├── logger.js │   ├── meta.js │   ├── phrases.js │   ├── utilities.js │   └── web.js ├── emails │   ├── _content.pug │   ├── _footer.pug │   ├── _nav.pug │   ├── account-update │   │   ├── html.pug │   │   └── subject.pug │   ├── change-email │   │   ├── html.pug │   │   └── subject.pug │   ├── inquiry │   │   ├── html.pug │   │   └── subject.pug │   ├── layout.pug │   ├── recovery │   │   ├── html.pug │   │   └── subject.pug │   ├── reset-password │   │   ├── html.pug │   │   └── subject.pug │   ├── two-factor-reminder │   │   ├── html.pug │   │   └── subject.pug │   ├── verify │   │   ├── html.pug │   │   └── subject.pug │   └── welcome │   ├── html.pug │   └── subject.pug ├── env ├── gitignore ├── gulpfile.js ├── helpers │   ├── email.js │   ├── get-email-locals.js │   ├── i18n.js │   ├── logger.js │   ├── markdown.js │   ├── passport.js │   ├── policies.js │   ├── send-verification-email.js │   └── to-object.js ├── index.js ├── jobs │   ├── account-updates.js │   ├── index.js │   ├── translate-markdown.js │   ├── translate-phrases.js │   ├── two-factor-reminder.js │   └── welcome-email.js ├── lad.sh ├── locales │   ├── ar.json │   ├── cs.json │   ├── da.json │   ├── de.json │   ├── en.json │   ├── es.json │   ├── fi.json │   ├── fr.json │   ├── he.json │   ├── hu.json │   ├── id.json │   ├── it.json │   ├── ja.json │   ├── ko.json │   ├── nl.json │   ├── no.json │   ├── pl.json │   ├── pt.json │   ├── ru.json │   ├── sv.json │   ├── th.json │   ├── tr.json │   ├── uk.json │   ├── vi.json │   └── zh.json ├── nodemon.json ├── package-scripts.js ├── package.json ├── proxy.js ├── routes │   ├── api │   │   ├── index.js │   │   └── v1 │   │   └── index.js │   ├── index.js │   └── web │   ├── admin.js │   ├── auth.js │   ├── index.js │   ├── my-account.js │   └── otp.js ├── template ├── web.js ├── yarn-error.log └── yarn.lock 42 directories, 212 files"><pre>template ├── LICENSE ├── README ├── ansible │   ├── playbooks │   │   ├── aws-credentials.yml │   │   ├── bree.yml │   │   ├── certificates.yml │   │   ├── deployment-keys.yml │   │   ├── ecosystem.yml │   │   ├── env.yml │   │   ├── gapp-creds.yml │   │   ├── http.yml │   │   ├── mongo.yml │   │   ├── node.yml │   │   ├── python.yml │   │   ├── redis.yml │   │   ├── security.yml │   │   ├── ssh-keys.yml │   │   └── templates │   │   ├── aws-credentials.j2 │   │   ├── before.rules.j2 │   │   ├── ecosystem-api.json.j2 │   │   ├── ecosystem-bree.json.j2 │   │   ├── ecosystem-web.json.j2 │   │   ├── env │   │   ├── hosts.yml │   │   └── security-limits.d-mongod.conf │   └── requirements.yml ├── ansible-playbook.js ├── ansible.cfg ├── api.js ├── app │   ├── controllers │   │   ├── api │   │   │   ├── index.js │   │   │   └── v1 │   │   │   ├── index.js │   │   │   ├── log.js │   │   │   └── users.js │   │   ├── index.js │   │   └── web │   │   ├── admin │   │   │   ├── index.js │   │   │   └── users.js │   │   ├── auth.js │   │   ├── index.js │   │   ├── my-account.js │   │   ├── otp │   │   │   ├── disable.js │   │   │   ├── index.js │   │   │   ├── keys.js │   │   │   ├── recovery.js │   │   │   └── setup.js │   │   ├── report.js │   │   └── support.js │   ├── models │   │   ├── index.js │   │   ├── inquiry.js │   │   └── user.js │   └── views │   ├── 404.pug │   ├── 500.pug │   ├── _breadcrumbs.pug │   ├── _footer.pug │   ├── _nav.pug │   ├── _pagination.pug │   ├── _register-or-login.pug │   ├── about.pug │   ├── admin │   │   ├── index.pug │   │   └── users │   │   ├── index.pug │   │   └── retrieve.pug │   ├── change-email.pug │   ├── dashboard │   │   └── index.pug │   ├── donate.pug │   ├── forgot-password.pug │   ├── home.pug │   ├── layout.pug │   ├── my-account │   │   ├── index.pug │   │   ├── profile.pug │   │   └── security.pug │   ├── otp │   │   ├── enable.pug │   │   ├── keys.pug │   │   ├── login.pug │   │   └── setup.pug │   ├── privacy.pug │   ├── register-or-login.pug │   ├── reset-password.pug │   ├── spinner │   │   ├── 1.pug │   │   ├── 10.pug │   │   ├── 11.pug │   │   ├── 2.pug │   │   ├── 3.pug │   │   ├── 4.pug │   │   ├── 5.pug │   │   ├── 6.pug │   │   ├── 7.pug │   │   ├── 8.pug │   │   ├── 9.pug │   │   └── spinner.pug │   ├── support.pug │   ├── terms.pug │   └── verify.pug ├── assets │   ├── browserconfig.xml │   ├── css │   │   ├── _btn-auth.scss │   │   ├── _custom.scss │   │   ├── _email.scss │   │   ├── _markdown.scss │   │   ├── _responsive-backgrounds.scss │   │   ├── _responsive-borders.scss │   │   ├── _responsive-rounded.scss │   │   ├── _swal2.scss │   │   ├── _variables.scss │   │   └── app.scss │   ├── fonts │   ├── img │   │   ├── android-chrome-192x192.png │   │   ├── android-chrome-384x384.png │   │   ├── apple-touch-icon.png │   │   ├── favicon-16x16.png │   │   ├── favicon-32x32.png │   │   ├── favicon.ico │   │   ├── github-logo.svg │   │   ├── google-logo.svg │   │   ├── logo-square.svg │   │   ├── mstile-150x150.png │   │   ├── social.png │   │   └── twitter.png │   ├── js │   │   ├── core.js │   │   ├── logger.js │   │   └── uncaught.js │   ├── robots.txt │   └── site.webmanifest ├── bree.js ├── config │   ├── api.js │   ├── bree.js │   ├── cookies.js │   ├── env.js │   ├── filters.js │   ├── i18n.js │   ├── index.js │   ├── koa-cash.js │   ├── locales.js │   ├── logger.js │   ├── meta.js │   ├── phrases.js │   ├── utilities.js │   └── web.js ├── emails │   ├── _content.pug │   ├── _footer.pug │   ├── _nav.pug │   ├── account-update │   │   ├── html.pug │   │   └── subject.pug │   ├── change-email │   │   ├── html.pug │   │   └── subject.pug │   ├── inquiry │   │   ├── html.pug │   │   └── subject.pug │   ├── layout.pug │   ├── recovery │   │   ├── html.pug │   │   └── subject.pug │   ├── reset-password │   │   ├── html.pug │   │   └── subject.pug │   ├── two-factor-reminder │   │   ├── html.pug │   │   └── subject.pug │   ├── verify │   │   ├── html.pug │   │   └── subject.pug │   └── welcome │   ├── html.pug │   └── subject.pug ├── env ├── gitignore ├── gulpfile.js ├── helpers │   ├── email.js │   ├── get-email-locals.js │   ├── i18n.js │   ├── logger.js │   ├── markdown.js │   ├── passport.js │   ├── policies.js │   ├── send-verification-email.js │   └── to-object.js ├── index.js ├── <span class="pl-c1">jobs</span> │   ├── account-updates.js │   ├── index.js │   ├── translate-markdown.js │   ├── translate-phrases.js │   ├── two-factor-reminder.js │   └── welcome-email.js ├── lad.sh ├── locales │   ├── ar.json │   ├── cs.json │   ├── da.json │   ├── de.json │   ├── en.json │   ├── es.json │   ├── fi.json │   ├── fr.json │   ├── he.json │   ├── hu.json │   ├── id.json │   ├── it.json │   ├── ja.json │   ├── ko.json │   ├── nl.json │   ├── no.json │   ├── pl.json │   ├── pt.json │   ├── ru.json │   ├── sv.json │   ├── th.json │   ├── tr.json │   ├── uk.json │   ├── vi.json │   └── zh.json ├── nodemon.json ├── package-scripts.js ├── package.json ├── proxy.js ├── routes │   ├── api │   │   ├── index.js │   │   └── v1 │   │   └── index.js │   ├── index.js │   └── web │   ├── admin.js │   ├── auth.js │   ├── index.js │   ├── my-account.js │   └── otp.js ├── template ├── web.js ├── yarn-error.log └── yarn.lock 42 directories, 212 files</pre></div> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Principles</h2><a id="user-content-principles" class="anchor" aria-label="Permalink: Principles" href="#principles"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">Lad is designed according to these principles:</p> <ol dir="auto"> <li>Always be developer-friendly</li> <li>Adhere to <a href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" rel="nofollow">MVC</a>, <a href="https://en.wikipedia.org/wiki/Unix_philosophy" rel="nofollow">Unix</a>, <a href="https://en.wikipedia.org/wiki/KISS_principle" rel="nofollow">KISS</a>, <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself" rel="nofollow">DRY</a>, <a href="https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it" rel="nofollow">YAGNI</a>, <a href="https://12factor.net/" rel="nofollow">Twelve Factor</a>, <a href="https://en.wikipedia.org/wiki/Occam%27s_razor" rel="nofollow">Occam's razor</a>, and <a href="https://en.wikipedia.org/wiki/Eating_your_own_dog_food" rel="nofollow">dogfooding</a></li> <li>Target the scrappy, bootstrapped, and <a href="http://www.paulgraham.com/ramenprofitable.html" rel="nofollow">ramen-profitable</a> hacker</li> </ol> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Related</h2><a id="user-content-related" class="anchor" aria-label="Permalink: Related" href="#related"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <ul dir="auto"> <li><a href="https://lipo.io" rel="nofollow">lipo</a> - Free image manipulation API service built on top of <a href="http://sharp.dimens.io/" rel="nofollow">Sharp</a></li> <li><a href="http://cabinjs.com" rel="nofollow">cabin</a> - Logging and analytics solution for <a href="https://nodejs.org" rel="nofollow">Node.js</a>, <a href="https://lad.js.org" rel="nofollow">Lad</a>, <a href="http://koajs.com/" rel="nofollow">Koa</a>, and <a href="https://expressjs.com" rel="nofollow">Express</a></li> <li><a href="https://lass.js.org" rel="nofollow">lass</a> - Scaffold a modern boilerplate for <a href="https://nodejs.org" rel="nofollow">Node.js</a></li> </ul> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Contributing</h2><a id="user-content-contributing" class="anchor" aria-label="Permalink: Contributing" href="#contributing"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">Interesting in contributing to this project or testing early releases?</p> <ol dir="auto"> <li> <p dir="auto">Follow all of the above <a href="#requirements">Requirements</a></p> </li> <li> <p dir="auto">You will need to fork and clone this repository locally</p> </li> <li> <p dir="auto">After forking, follow these steps:</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="cd lad yarn install cd template yarn install yarn start"><pre><span class="pl-c1">cd</span> lad yarn install <span class="pl-c1">cd</span> template yarn install yarn start</pre></div> </li> </ol> <p dir="auto">If you'd like to preview changes to the <code>README.md</code> file, you can use <code>docute</code>.</p> <div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="yarn global add docute-cli cd lad docute ./"><pre>yarn global add docute-cli <span class="pl-c1">cd</span> lad docute ./</pre></div> <p dir="auto">Then visit <a href="http://localhost:8080" rel="nofollow">http://localhost:8080</a> in your browser.</p> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Contributors</h2><a id="user-content-contributors" class="anchor" aria-label="Permalink: Contributors" href="#contributors"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <markdown-accessiblity-table><table> <thead> <tr> <th>Name</th> <th>Website</th> </tr> </thead> <tbody> <tr> <td><strong>Nick Baugh</strong></td> <td><a href="http://niftylettuce.com" rel="nofollow">http://niftylettuce.com</a></td> </tr> <tr> <td><strong>Shaun Warman</strong></td> <td><a href="https://shaunwarman.com/" rel="nofollow">https://shaunwarman.com/</a></td> </tr> </tbody> </table></markdown-accessiblity-table> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Trademark Notice</h2><a id="user-content-trademark-notice" class="anchor" aria-label="Permalink: Trademark Notice" href="#trademark-notice"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto">Lad, Lass, Cabin, Lipo, and their respective logos are trademarks of Niftylettuce LLC. These trademarks may not be reproduced, distributed, transmitted, or otherwise used, except with the prior written permission of Niftylettuce LLC. If you are seeking permission to use these trademarks, then please <a href="mailto:niftylettuce@gmail.com">contact us</a>.</p> <div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">License</h2><a id="user-content-license" class="anchor" aria-label="Permalink: License" href="#license"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div> <p dir="auto"><a href="/ladjs/lad/blob/snyk-fix-bed97d0c625fc25446b4c14528f312d1/LICENSE">MIT</a> © <a href="http://niftylettuce.com" rel="nofollow">Nick Baugh</a></p> <h2 dir="auto"></h2> <p dir="auto"><a href="#"><img src="/ladjs/lad/raw/snyk-fix-bed97d0c625fc25446b4c14528f312d1/media/lad-footer.png" alt="#" style="max-width: 100%;"></a></p> </article></div></div></div></div></div> <!-- --> <!-- --> <script type="application/json" id="__PRIMER_DATA_:R0:__">{"resolvedServerColorMode":"day"}</script></div> </react-partial> <input type="hidden" data-csrf="true" value="4wKDdnYG/FyJkayuk2y0knmTVLTbSU/0fo8d4JpKMIbbi33dLLZxKvc4Oua8wrg2DMdbu7f4VYDOXQXAP11wXw==" /> </div> <div data-view-component="true" class="Layout-sidebar"> <div class="BorderGrid about-margin" data-pjax> <div class="BorderGrid-row"> <div class="BorderGrid-cell"> <div class="hide-sm hide-md"> <h2 class="mb-3 h4">About</h2> <p class="f4 my-3"> Node.js framework made by a former <a class="user-mention" data-hovercard-type="organization" data-hovercard-url="/orgs/expressjs/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/expressjs">@expressjs</a> TC and <a class="user-mention" data-hovercard-type="organization" data-hovercard-url="/orgs/koajs/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/koajs">@koajs</a> team member. Built for <a class="user-mention" data-hovercard-type="organization" data-hovercard-url="/orgs/forwardemail/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/forwardemail">@forwardemail</a>, <a class="user-mention" data-hovercard-type="organization" data-hovercard-url="/orgs/spamscanner/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/spamscanner">@spamscanner</a>, <a class="user-mention" data-hovercard-type="organization" data-hovercard-url="/orgs/breejs/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/breejs">@breejs</a>, <a class="user-mention" data-hovercard-type="organization" data-hovercard-url="/orgs/cabinjs/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/cabinjs">@cabinjs</a>, and <a class="user-mention" data-hovercard-type="organization" data-hovercard-url="/orgs/lassjs/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/lassjs">@lassjs</a>. </p> <div class="my-3 d-flex flex-items-center"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-link flex-shrink-0 mr-2"> <path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path> </svg> <span class="flex-auto min-width-0 css-truncate css-truncate-target width-fit"> <a title="https://lad.js.org" role="link" target="_blank" rel="noopener noreferrer nofollow" class="text-bold" href="https://lad.js.org">lad.js.org</a> </span> </div> <h3 class="sr-only">Topics</h3> <div class="my-3"> <div class="f6"> <a href="/topics/nodejs" title="Topic: nodejs" data-view-component="true" class="topic-tag topic-tag-link"> nodejs </a> <a href="/topics/javascript" title="Topic: javascript" data-view-component="true" class="topic-tag topic-tag-link"> javascript </a> <a href="/topics/api" title="Topic: api" data-view-component="true" class="topic-tag topic-tag-link"> api </a> <a href="/topics/bootstrap" title="Topic: bootstrap" data-view-component="true" class="topic-tag topic-tag-link"> bootstrap </a> <a href="/topics/redis" title="Topic: redis" data-view-component="true" class="topic-tag topic-tag-link"> redis </a> <a href="/topics/aws" title="Topic: aws" data-view-component="true" class="topic-tag topic-tag-link"> aws </a> <a href="/topics/boilerplate" title="Topic: boilerplate" data-view-component="true" class="topic-tag topic-tag-link"> boilerplate </a> <a href="/topics/koa" title="Topic: koa" data-view-component="true" class="topic-tag topic-tag-link"> koa </a> <a href="/topics/framework" title="Topic: framework" data-view-component="true" class="topic-tag topic-tag-link"> framework </a> <a href="/topics/react-native" title="Topic: react-native" data-view-component="true" class="topic-tag topic-tag-link"> react-native </a> <a href="/topics/mvc" title="Topic: mvc" data-view-component="true" class="topic-tag topic-tag-link"> mvc </a> <a href="/topics/mongodb" title="Topic: mongodb" data-view-component="true" class="topic-tag topic-tag-link"> mongodb </a> <a href="/topics/mongoose" title="Topic: mongoose" data-view-component="true" class="topic-tag topic-tag-link"> mongoose </a> <a href="/topics/s3" title="Topic: s3" data-view-component="true" class="topic-tag topic-tag-link"> s3 </a> <a href="/topics/prettier" title="Topic: prettier" data-view-component="true" class="topic-tag topic-tag-link"> prettier </a> <a href="/topics/passport" title="Topic: passport" data-view-component="true" class="topic-tag topic-tag-link"> passport </a> <a href="/topics/ava" title="Topic: ava" data-view-component="true" class="topic-tag topic-tag-link"> ava </a> <a href="/topics/xo" title="Topic: xo" data-view-component="true" class="topic-tag topic-tag-link"> xo </a> <a href="/topics/cloudfront" title="Topic: cloudfront" data-view-component="true" class="topic-tag topic-tag-link"> cloudfront </a> <a href="/topics/async-await" title="Topic: async-await" data-view-component="true" class="topic-tag topic-tag-link"> async-await </a> </div> </div> <h3 class="sr-only">Resources</h3> <div class="mt-2"> <a class="Link--muted" data-analytics-event="{&quot;category&quot;:&quot;Repository Overview&quot;,&quot;action&quot;:&quot;click&quot;,&quot;label&quot;:&quot;location:sidebar;file:readme&quot;}" href="#readme-ov-file"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-book mr-2"> <path d="M0 1.75A.75.75 0 0 1 .75 1h4.253c1.227 0 2.317.59 3 1.501A3.743 3.743 0 0 1 11.006 1h4.245a.75.75 0 0 1 .75.75v10.5a.75.75 0 0 1-.75.75h-4.507a2.25 2.25 0 0 0-1.591.659l-.622.621a.75.75 0 0 1-1.06 0l-.622-.621A2.25 2.25 0 0 0 5.258 13H.75a.75.75 0 0 1-.75-.75Zm7.251 10.324.004-5.073-.002-2.253A2.25 2.25 0 0 0 5.003 2.5H1.5v9h3.757a3.75 3.75 0 0 1 1.994.574ZM8.755 4.75l-.004 7.322a3.752 3.752 0 0 1 1.992-.572H14.5v-9h-3.495a2.25 2.25 0 0 0-2.25 2.25Z"></path> </svg> Readme </a> </div> <h3 class="sr-only">License</h3> <div class="mt-2"> <a href="/ladjs/lad/blob/master/LICENSE" class="Link--muted" data-analytics-event="{&quot;category&quot;:&quot;Repository Overview&quot;,&quot;action&quot;:&quot;click&quot;,&quot;label&quot;:&quot;location:sidebar;file:license&quot;}" > <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-law mr-2"> <path d="M8.75.75V2h.985c.304 0 .603.08.867.231l1.29.736c.038.022.08.033.124.033h2.234a.75.75 0 0 1 0 1.5h-.427l2.111 4.692a.75.75 0 0 1-.154.838l-.53-.53.529.531-.001.002-.002.002-.006.006-.006.005-.01.01-.045.04c-.21.176-.441.327-.686.45C14.556 10.78 13.88 11 13 11a4.498 4.498 0 0 1-2.023-.454 3.544 3.544 0 0 1-.686-.45l-.045-.04-.016-.015-.006-.006-.004-.004v-.001a.75.75 0 0 1-.154-.838L12.178 4.5h-.162c-.305 0-.604-.079-.868-.231l-1.29-.736a.245.245 0 0 0-.124-.033H8.75V13h2.5a.75.75 0 0 1 0 1.5h-6.5a.75.75 0 0 1 0-1.5h2.5V3.5h-.984a.245.245 0 0 0-.124.033l-1.289.737c-.265.15-.564.23-.869.23h-.162l2.112 4.692a.75.75 0 0 1-.154.838l-.53-.53.529.531-.001.002-.002.002-.006.006-.016.015-.045.04c-.21.176-.441.327-.686.45C4.556 10.78 3.88 11 3 11a4.498 4.498 0 0 1-2.023-.454 3.544 3.544 0 0 1-.686-.45l-.045-.04-.016-.015-.006-.006-.004-.004v-.001a.75.75 0 0 1-.154-.838L2.178 4.5H1.75a.75.75 0 0 1 0-1.5h2.234a.249.249 0 0 0 .125-.033l1.288-.737c.265-.15.564-.23.869-.23h.984V.75a.75.75 0 0 1 1.5 0Zm2.945 8.477c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L13 6.327Zm-10 0c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L3 6.327Z"></path> </svg> MIT license </a> </div> <h3 class="sr-only">Code of conduct</h3> <div class="mt-2"> <a href="#coc-ov-file" class="Link--muted" data-analytics-event="{&quot;category&quot;:&quot;Repository Overview&quot;,&quot;action&quot;:&quot;click&quot;,&quot;label&quot;:&quot;location:sidebar;file:code of conduct&quot;}" > <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-code-of-conduct mr-2"> <path d="M8.048 2.241c.964-.709 2.079-1.238 3.325-1.241a4.616 4.616 0 0 1 3.282 1.355c.41.408.757.86.996 1.428.238.568.348 1.206.347 1.968 0 2.193-1.505 4.254-3.081 5.862-1.496 1.526-3.213 2.796-4.249 3.563l-.22.163a.749.749 0 0 1-.895 0l-.221-.163c-1.036-.767-2.753-2.037-4.249-3.563C1.51 10.008.007 7.952.002 5.762a4.614 4.614 0 0 1 1.353-3.407C3.123.585 6.223.537 8.048 2.24Zm-1.153.983c-1.25-1.033-3.321-.967-4.48.191a3.115 3.115 0 0 0-.913 2.335c0 1.556 1.109 3.24 2.652 4.813C5.463 11.898 6.96 13.032 8 13.805c.353-.262.758-.565 1.191-.905l-1.326-1.223a.75.75 0 0 1 1.018-1.102l1.48 1.366c.328-.281.659-.577.984-.887L9.99 9.802a.75.75 0 1 1 1.019-1.103l1.384 1.28c.295-.329.566-.661.81-.995L12.92 8.7l-1.167-1.168c-.674-.671-1.78-.664-2.474.03-.268.269-.538.537-.802.797-.893.882-2.319.843-3.185-.032-.346-.35-.693-.697-1.043-1.047a.75.75 0 0 1-.04-1.016c.162-.191.336-.401.52-.623.62-.748 1.356-1.637 2.166-2.417Zm7.112 4.442c.313-.65.491-1.293.491-1.916v-.001c0-.614-.088-1.045-.23-1.385-.143-.339-.357-.633-.673-.949a3.111 3.111 0 0 0-2.218-.915c-1.092.003-2.165.627-3.226 1.602-.823.755-1.554 1.637-2.228 2.45l-.127.154.562.566a.755.755 0 0 0 1.066.02l.794-.79c1.258-1.258 3.312-1.31 4.594-.032.396.394.792.791 1.173 1.173Z"></path> </svg> Code of conduct </a> </div> <h3 class="sr-only">Security policy</h3> <div class="mt-2"> <a href="#security-ov-file" class="Link--muted" data-analytics-event="{&quot;category&quot;:&quot;Repository Overview&quot;,&quot;action&quot;:&quot;click&quot;,&quot;label&quot;:&quot;location:sidebar;file:security policy&quot;}" > <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-law mr-2"> <path d="M8.75.75V2h.985c.304 0 .603.08.867.231l1.29.736c.038.022.08.033.124.033h2.234a.75.75 0 0 1 0 1.5h-.427l2.111 4.692a.75.75 0 0 1-.154.838l-.53-.53.529.531-.001.002-.002.002-.006.006-.006.005-.01.01-.045.04c-.21.176-.441.327-.686.45C14.556 10.78 13.88 11 13 11a4.498 4.498 0 0 1-2.023-.454 3.544 3.544 0 0 1-.686-.45l-.045-.04-.016-.015-.006-.006-.004-.004v-.001a.75.75 0 0 1-.154-.838L12.178 4.5h-.162c-.305 0-.604-.079-.868-.231l-1.29-.736a.245.245 0 0 0-.124-.033H8.75V13h2.5a.75.75 0 0 1 0 1.5h-6.5a.75.75 0 0 1 0-1.5h2.5V3.5h-.984a.245.245 0 0 0-.124.033l-1.289.737c-.265.15-.564.23-.869.23h-.162l2.112 4.692a.75.75 0 0 1-.154.838l-.53-.53.529.531-.001.002-.002.002-.006.006-.016.015-.045.04c-.21.176-.441.327-.686.45C4.556 10.78 3.88 11 3 11a4.498 4.498 0 0 1-2.023-.454 3.544 3.544 0 0 1-.686-.45l-.045-.04-.016-.015-.006-.006-.004-.004v-.001a.75.75 0 0 1-.154-.838L2.178 4.5H1.75a.75.75 0 0 1 0-1.5h2.234a.249.249 0 0 0 .125-.033l1.288-.737c.265-.15.564-.23.869-.23h.984V.75a.75.75 0 0 1 1.5 0Zm2.945 8.477c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L13 6.327Zm-10 0c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L3 6.327Z"></path> </svg> Security policy </a> </div> <include-fragment src="/ladjs/lad/hovercards/citation/sidebar_partial?tree_name=snyk-fix-bed97d0c625fc25446b4c14528f312d1"> </include-fragment> <div class="mt-2"> <a href="/ladjs/lad/activity" data-view-component="true" class="Link Link--muted"><svg text="gray" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-pulse mr-2"> <path d="M6 2c.306 0 .582.187.696.471L10 10.731l1.304-3.26A.751.751 0 0 1 12 7h3.25a.75.75 0 0 1 0 1.5h-2.742l-1.812 4.528a.751.751 0 0 1-1.392 0L6 4.77 4.696 8.03A.75.75 0 0 1 4 8.5H.75a.75.75 0 0 1 0-1.5h2.742l1.812-4.529A.751.751 0 0 1 6 2Z"></path> </svg> <span class="color-fg-muted">Activity</span></a> </div> <div class="mt-2"> <a href="/ladjs/lad/custom-properties" data-view-component="true" class="Link Link--muted"><svg text="gray" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-note mr-2"> <path d="M0 3.75C0 2.784.784 2 1.75 2h12.5c.966 0 1.75.784 1.75 1.75v8.5A1.75 1.75 0 0 1 14.25 14H1.75A1.75 1.75 0 0 1 0 12.25Zm1.75-.25a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-8.5a.25.25 0 0 0-.25-.25ZM3.5 6.25a.75.75 0 0 1 .75-.75h7a.75.75 0 0 1 0 1.5h-7a.75.75 0 0 1-.75-.75Zm.75 2.25h4a.75.75 0 0 1 0 1.5h-4a.75.75 0 0 1 0-1.5Z"></path> </svg> <span class="color-fg-muted">Custom properties</span></a> </div> <h3 class="sr-only">Stars</h3> <div class="mt-2"> <a href="/ladjs/lad/stargazers" data-view-component="true" class="Link Link--muted"><svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-star mr-2"> <path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Zm0 2.445L6.615 5.5a.75.75 0 0 1-.564.41l-3.097.45 2.24 2.184a.75.75 0 0 1 .216.664l-.528 3.084 2.769-1.456a.75.75 0 0 1 .698 0l2.77 1.456-.53-3.084a.75.75 0 0 1 .216-.664l2.24-2.183-3.096-.45a.75.75 0 0 1-.564-.41L8 2.694Z"></path> </svg> <strong>2.3k</strong> stars</a> </div> <h3 class="sr-only">Watchers</h3> <div class="mt-2"> <a href="/ladjs/lad/watchers" data-view-component="true" class="Link Link--muted"><svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-eye mr-2"> <path d="M8 2c1.981 0 3.671.992 4.933 2.078 1.27 1.091 2.187 2.345 2.637 3.023a1.62 1.62 0 0 1 0 1.798c-.45.678-1.367 1.932-2.637 3.023C11.67 13.008 9.981 14 8 14c-1.981 0-3.671-.992-4.933-2.078C1.797 10.83.88 9.576.43 8.898a1.62 1.62 0 0 1 0-1.798c.45-.677 1.367-1.931 2.637-3.022C4.33 2.992 6.019 2 8 2ZM1.679 7.932a.12.12 0 0 0 0 .136c.411.622 1.241 1.75 2.366 2.717C5.176 11.758 6.527 12.5 8 12.5c1.473 0 2.825-.742 3.955-1.715 1.124-.967 1.954-2.096 2.366-2.717a.12.12 0 0 0 0-.136c-.412-.621-1.242-1.75-2.366-2.717C10.824 4.242 9.473 3.5 8 3.5c-1.473 0-2.825.742-3.955 1.715-1.124.967-1.954 2.096-2.366 2.717ZM8 10a2 2 0 1 1-.001-3.999A2 2 0 0 1 8 10Z"></path> </svg> <strong>57</strong> watching</a> </div> <h3 class="sr-only">Forks</h3> <div class="mt-2"> <a href="/ladjs/lad/forks" data-view-component="true" class="Link Link--muted"><svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-repo-forked mr-2"> <path d="M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 1 1.5 0v.878a2.25 2.25 0 0 1-2.25 2.25h-1.5v2.128a2.251 2.251 0 1 1-1.5 0V8.5h-1.5A2.25 2.25 0 0 1 3.5 6.25v-.878a2.25 2.25 0 1 1 1.5 0ZM5 3.25a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Zm6.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm-3 8.75a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Z"></path> </svg> <strong>154</strong> forks</a> </div> <div class="mt-2"> <a class="Link--muted" href="/contact/report-content?content_url=https%3A%2F%2Fgithub.com%2Fladjs%2Flad&amp;report=ladjs+%28user%29"> Report repository </a> </div> </div> </div> </div> <div class="BorderGrid-row"> <div class="BorderGrid-cell"> <h2 class="h4 mb-3" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame"> <a href="/ladjs/lad/releases" data-view-component="true" class="Link--primary no-underline Link">Releases <span title="38" data-view-component="true" class="Counter">38</span></a></h2> <a class="Link--primary d-flex no-underline" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" href="/ladjs/lad/releases/tag/v1.3.2"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-tag flex-shrink-0 mt-1 color-fg-success"> <path d="M1 7.775V2.75C1 1.784 1.784 1 2.75 1h5.025c.464 0 .91.184 1.238.513l6.25 6.25a1.75 1.75 0 0 1 0 2.474l-5.026 5.026a1.75 1.75 0 0 1-2.474 0l-6.25-6.25A1.752 1.752 0 0 1 1 7.775Zm1.5 0c0 .066.026.13.073.177l6.25 6.25a.25.25 0 0 0 .354 0l5.025-5.025a.25.25 0 0 0 0-.354l-6.25-6.25a.25.25 0 0 0-.177-.073H2.75a.25.25 0 0 0-.25.25ZM6 5a1 1 0 1 1 0 2 1 1 0 0 1 0-2Z"></path> </svg> <div class="ml-2 min-width-0"> <div class="d-flex"> <span class="css-truncate css-truncate-target text-bold mr-2" style="max-width: none;">v1.3.2</span> <span title="Label: Latest" data-view-component="true" class="Label Label--success flex-shrink-0"> Latest </span> </div> <div class="text-small color-fg-muted"><relative-time datetime="2022-04-27T16:44:06Z" class="no-wrap">Apr 27, 2022</relative-time></div> </div> </a> <div data-view-component="true" class="mt-3"> <a text="small" data-pjax="#repo-content-pjax-container" data-turbo-frame="repo-content-turbo-frame" href="/ladjs/lad/releases" data-view-component="true" class="Link">+ 37 releases</a></div> </div> </div> <div class="BorderGrid-row"> <div class="BorderGrid-cell"> <h2 class="h4 mb-3">Sponsor this project</h2> <include-fragment src="/ladjs/lad/sponsors_list?block_button=false&amp;current_repository=lad" aria-busy="true" aria-label="Loading sponsorable links"> <ul class="list-style-none"> </ul> </include-fragment> <ul class="list-style-none"> <li class="mb-2 d-flex"> <span class="mr-2 d-flex flex-items-center flex-justify-center" style="min-width:32px;height:32px;"> <img width="32" height="32" class="octicon rounded-2 d-block" alt="patreon" src="https://github.githubassets.com/assets/patreon-96b15b9db4b9.svg" /> </span> <span class="flex-self-center flex-auto min-width-0 css-truncate css-truncate-target width-fit"> <a target="_blank" data-ga-click="Dashboard, click, Nav menu - item:org-profile context:organization" data-hydro-click="{&quot;event_type&quot;:&quot;sponsors.repo_funding_links_link_click&quot;,&quot;payload&quot;:{&quot;platform&quot;:{&quot;platform_type&quot;:&quot;PATREON&quot;,&quot;platform_url&quot;:&quot;https://patreon.com/niftylettuce&quot;},&quot;platforms&quot;:[{&quot;platform_type&quot;:&quot;PATREON&quot;,&quot;platform_url&quot;:&quot;https://patreon.com/niftylettuce&quot;}],&quot;repo_id&quot;:2791470,&quot;owner_id&quot;:30959108,&quot;user_id&quot;:null,&quot;originating_url&quot;:&quot;https://github.com/ladjs/lad/tree/snyk-fix-bed97d0c625fc25446b4c14528f312d1&quot;}}" data-hydro-click-hmac="9fc500c713e0b11c794e8ba9c9c6915e1cbe48f6e9b83e1054ae521597f2474e" href="https://patreon.com/niftylettuce"><span>patreon.com/<strong>niftylettuce</strong></span></a> </span> </li> </ul> </div> </div> <div class="BorderGrid-row"> <div class="BorderGrid-cell"> <h2 class="h4 mb-3"> <a href="/orgs/ladjs/packages?repo_name=lad" data-view-component="true" class="Link--primary no-underline Link d-flex flex-items-center">Packages <span title="0" hidden="hidden" data-view-component="true" class="Counter ml-1">0</span></a></h2> <div class="text-small color-fg-muted" > No packages published <br> </div> </div> </div> <div class="BorderGrid-row" hidden> <div class="BorderGrid-cell"> <include-fragment src="/ladjs/lad/used_by_list" accept="text/fragment+html"> </include-fragment> </div> </div> <div class="BorderGrid-row"> <div class="BorderGrid-cell"> <h2 class="h4 mb-3"> <a href="/ladjs/lad/graphs/contributors" data-view-component="true" class="Link--primary no-underline Link d-flex flex-items-center">Contributors <span title="11" data-view-component="true" class="Counter ml-1">11</span></a></h2> <include-fragment src="/ladjs/lad/contributors_list?count=11&amp;current_repository=lad&amp;items_to_show=11" aria-busy="true" aria-label="Loading contributors"> <ul class="list-style-none d-flex flex-wrap mb-n2"> <li class="mb-2 "> <div class="Skeleton avatar avatar-user mr-2" style="width:32px;height:32px;"></div> </li> <li class="mb-2 "> <div class="Skeleton avatar avatar-user mr-2" style="width:32px;height:32px;"></div> </li> <li class="mb-2 "> <div class="Skeleton avatar avatar-user mr-2" style="width:32px;height:32px;"></div> </li> <li class="mb-2 "> <div class="Skeleton avatar avatar-user mr-2" style="width:32px;height:32px;"></div> </li> <li class="mb-2 "> <div class="Skeleton avatar avatar-user mr-2" style="width:32px;height:32px;"></div> </li> <li class="mb-2 "> <div class="Skeleton avatar avatar-user mr-2" style="width:32px;height:32px;"></div> </li> <li class="mb-2 "> <div class="Skeleton avatar avatar-user mr-2" style="width:32px;height:32px;"></div> </li> <li class="mb-2 "> <div class="Skeleton avatar avatar-user mr-2" style="width:32px;height:32px;"></div> </li> <li class="mb-2 "> <div class="Skeleton avatar avatar-user mr-2" style="width:32px;height:32px;"></div> </li> <li class="mb-2 "> <div class="Skeleton avatar avatar-user mr-2" style="width:32px;height:32px;"></div> </li> <li class="mb-2 "> <div class="Skeleton avatar avatar-user mr-2" style="width:32px;height:32px;"></div> </li> </ul> </include-fragment> </div> </div> <div class="BorderGrid-row"> <div class="BorderGrid-cell"> <h2 class="h4 mb-3">Languages</h2> <div class="mb-2"> <span data-view-component="true" class="Progress"> <span style="background-color:#f1e05a !important;;width: 63.2%;" itemprop="keywords" data-view-component="true" class="Progress-item color-bg-success-emphasis"></span> <span style="background-color:#a86454 !important;;width: 29.4%;" itemprop="keywords" data-view-component="true" class="Progress-item color-bg-success-emphasis"></span> <span style="background-color:#c6538c !important;;width: 4.3%;" itemprop="keywords" data-view-component="true" class="Progress-item color-bg-success-emphasis"></span> <span style="background-color:#a52a22 !important;;width: 2.4%;" itemprop="keywords" data-view-component="true" class="Progress-item color-bg-success-emphasis"></span> <span style="background-color:#e34c26 !important;;width: 0.7%;" itemprop="keywords" data-view-component="true" class="Progress-item color-bg-success-emphasis"></span> </span></div> <ul class="list-style-none"> <li class="d-inline"> <a class="d-inline-flex flex-items-center flex-nowrap Link--secondary no-underline text-small mr-3" href="/ladjs/lad/search?l=javascript" data-ga-click="Repository, language stats search click, location:repo overview"> <svg style="color:#f1e05a;" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-dot-fill mr-2"> <path d="M8 4a4 4 0 1 1 0 8 4 4 0 0 1 0-8Z"></path> </svg> <span class="color-fg-default text-bold mr-1">JavaScript</span> <span>63.2%</span> </a> </li> <li class="d-inline"> <a class="d-inline-flex flex-items-center flex-nowrap Link--secondary no-underline text-small mr-3" href="/ladjs/lad/search?l=pug" data-ga-click="Repository, language stats search click, location:repo overview"> <svg style="color:#a86454;" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-dot-fill mr-2"> <path d="M8 4a4 4 0 1 1 0 8 4 4 0 0 1 0-8Z"></path> </svg> <span class="color-fg-default text-bold mr-1">Pug</span> <span>29.4%</span> </a> </li> <li class="d-inline"> <a class="d-inline-flex flex-items-center flex-nowrap Link--secondary no-underline text-small mr-3" href="/ladjs/lad/search?l=scss" data-ga-click="Repository, language stats search click, location:repo overview"> <svg style="color:#c6538c;" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-dot-fill mr-2"> <path d="M8 4a4 4 0 1 1 0 8 4 4 0 0 1 0-8Z"></path> </svg> <span class="color-fg-default text-bold mr-1">SCSS</span> <span>4.3%</span> </a> </li> <li class="d-inline"> <a class="d-inline-flex flex-items-center flex-nowrap Link--secondary no-underline text-small mr-3" href="/ladjs/lad/search?l=jinja" data-ga-click="Repository, language stats search click, location:repo overview"> <svg style="color:#a52a22;" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-dot-fill mr-2"> <path d="M8 4a4 4 0 1 1 0 8 4 4 0 0 1 0-8Z"></path> </svg> <span class="color-fg-default text-bold mr-1">Jinja</span> <span>2.4%</span> </a> </li> <li class="d-inline"> <a class="d-inline-flex flex-items-center flex-nowrap Link--secondary no-underline text-small mr-3" href="/ladjs/lad/search?l=html" data-ga-click="Repository, language stats search click, location:repo overview"> <svg style="color:#e34c26;" aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-dot-fill mr-2"> <path d="M8 4a4 4 0 1 1 0 8 4 4 0 0 1 0-8Z"></path> </svg> <span class="color-fg-default text-bold mr-1">HTML</span> <span>0.7%</span> </a> </li> </ul> </div> </div> </div> </div> </div></div> </div> </div> </turbo-frame> </main> </div> </div> <footer class="footer pt-8 pb-6 f6 color-fg-muted p-responsive" role="contentinfo" > <h2 class='sr-only'>Footer</h2> <div class="d-flex flex-justify-center flex-items-center flex-column-reverse flex-lg-row flex-wrap flex-lg-nowrap"> <div class="d-flex flex-items-center flex-shrink-0 mx-2"> <a aria-label="Homepage" title="GitHub" class="footer-octicon mr-2" href="https://github.com"> <svg aria-hidden="true" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-mark-github"> <path d="M12 1C5.9225 1 1 5.9225 1 12C1 16.8675 4.14875 20.9787 8.52125 22.4362C9.07125 22.5325 9.2775 22.2025 9.2775 21.9137C9.2775 21.6525 9.26375 20.7862 9.26375 19.865C6.5 20.3737 5.785 19.1912 5.565 18.5725C5.44125 18.2562 4.905 17.28 4.4375 17.0187C4.0525 16.8125 3.5025 16.3037 4.42375 16.29C5.29 16.2762 5.90875 17.0875 6.115 17.4175C7.105 19.0812 8.68625 18.6137 9.31875 18.325C9.415 17.61 9.70375 17.1287 10.02 16.8537C7.5725 16.5787 5.015 15.63 5.015 11.4225C5.015 10.2262 5.44125 9.23625 6.1425 8.46625C6.0325 8.19125 5.6475 7.06375 6.2525 5.55125C6.2525 5.55125 7.17375 5.2625 9.2775 6.67875C10.1575 6.43125 11.0925 6.3075 12.0275 6.3075C12.9625 6.3075 13.8975 6.43125 14.7775 6.67875C16.8813 5.24875 17.8025 5.55125 17.8025 5.55125C18.4075 7.06375 18.0225 8.19125 17.9125 8.46625C18.6138 9.23625 19.04 10.2125 19.04 11.4225C19.04 15.6437 16.4688 16.5787 14.0213 16.8537C14.42 17.1975 14.7638 17.8575 14.7638 18.8887C14.7638 20.36 14.75 21.5425 14.75 21.9137C14.75 22.2025 14.9563 22.5462 15.5063 22.4362C19.8513 20.9787 23 16.8537 23 12C23 5.9225 18.0775 1 12 1Z"></path> </svg> </a> <span> &copy; 2025 GitHub,&nbsp;Inc. </span> </div> <nav aria-label="Footer"> <h3 class="sr-only" id="sr-footer-heading">Footer navigation</h3> <ul class="list-style-none d-flex flex-justify-center flex-wrap mb-2 mb-lg-0" aria-labelledby="sr-footer-heading"> <li class="mx-2"> <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to Terms&quot;,&quot;label&quot;:&quot;text:terms&quot;}" href="https://docs.github.com/site-policy/github-terms/github-terms-of-service" data-view-component="true" class="Link--secondary Link">Terms</a> </li> <li class="mx-2"> <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to privacy&quot;,&quot;label&quot;:&quot;text:privacy&quot;}" href="https://docs.github.com/site-policy/privacy-policies/github-privacy-statement" data-view-component="true" class="Link--secondary Link">Privacy</a> </li> <li class="mx-2"> <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to security&quot;,&quot;label&quot;:&quot;text:security&quot;}" href="https://github.com/security" data-view-component="true" class="Link--secondary Link">Security</a> </li> <li class="mx-2"> <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to status&quot;,&quot;label&quot;:&quot;text:status&quot;}" href="https://www.githubstatus.com/" data-view-component="true" class="Link--secondary Link">Status</a> </li> <li class="mx-2"> <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to docs&quot;,&quot;label&quot;:&quot;text:docs&quot;}" href="https://docs.github.com/" data-view-component="true" class="Link--secondary Link">Docs</a> </li> <li class="mx-2"> <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to contact&quot;,&quot;label&quot;:&quot;text:contact&quot;}" href="https://support.github.com?tags=dotcom-footer" data-view-component="true" class="Link--secondary Link">Contact</a> </li> <li class="mx-2" > <cookie-consent-link> <button type="button" class="Link--secondary underline-on-hover border-0 p-0 color-bg-transparent" data-action="click:cookie-consent-link#showConsentManagement" data-analytics-event="{&quot;location&quot;:&quot;footer&quot;,&quot;action&quot;:&quot;cookies&quot;,&quot;context&quot;:&quot;subfooter&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;cookies_link_subfooter_footer&quot;}" > Manage cookies </button> </cookie-consent-link> </li> <li class="mx-2"> <cookie-consent-link> <button type="button" class="Link--secondary underline-on-hover border-0 p-0 color-bg-transparent" data-action="click:cookie-consent-link#showConsentManagement" data-analytics-event="{&quot;location&quot;:&quot;footer&quot;,&quot;action&quot;:&quot;dont_share_info&quot;,&quot;context&quot;:&quot;subfooter&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;dont_share_info_link_subfooter_footer&quot;}" > Do not share my personal information </button> </cookie-consent-link> </li> </ul> </nav> </div> </footer> <ghcc-consent id="ghcc" class="position-fixed bottom-0 left-0" style="z-index: 999999" data-initial-cookie-consent-allowed="" data-cookie-consent-required="false"></ghcc-consent> <div id="ajax-error-message" class="ajax-error-message flash flash-error" hidden> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert"> <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path> </svg> <button type="button" class="flash-close js-ajax-error-dismiss" aria-label="Dismiss error"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x"> <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> </svg> </button> You can’t perform that action at this time. </div> <template id="site-details-dialog"> <details class="details-reset details-overlay details-overlay-dark lh-default color-fg-default hx_rsm" open> <summary role="button" aria-label="Close dialog"></summary> <details-dialog class="Box Box--overlay d-flex flex-column anim-fade-in fast hx_rsm-dialog hx_rsm-modal"> <button class="Box-btn-octicon m-0 btn-octicon position-absolute right-0 top-0" type="button" aria-label="Close dialog" data-close-dialog> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x"> <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path> </svg> </button> <div class="octocat-spinner my-6 js-details-dialog-spinner"></div> </details-dialog> </details> </template> <div class="Popover js-hovercard-content position-absolute" style="display: none; outline: none;"> <div class="Popover-message Popover-message--bottom-left Popover-message--large Box color-shadow-large" style="width:360px;"> </div> </div> <template id="snippet-clipboard-copy-button"> <div class="zeroclipboard-container position-absolute right-0 top-0"> <clipboard-copy aria-label="Copy" class="ClipboardButton btn js-clipboard-copy m-2 p-0" data-copy-feedback="Copied!" data-tooltip-direction="w"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon m-2"> <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> </svg> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success d-none m-2"> <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path> </svg> </clipboard-copy> </div> </template> <template id="snippet-clipboard-copy-button-unpositioned"> <div class="zeroclipboard-container"> <clipboard-copy aria-label="Copy" class="ClipboardButton btn btn-invisible js-clipboard-copy m-2 p-0 d-flex flex-justify-center flex-items-center" data-copy-feedback="Copied!" data-tooltip-direction="w"> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon"> <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path> </svg> <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success d-none"> <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path> </svg> </clipboard-copy> </div> </template> </div> <div id="js-global-screen-reader-notice" class="sr-only mt-n1" aria-live="polite" aria-atomic="true" ></div> <div id="js-global-screen-reader-notice-assertive" class="sr-only mt-n1" aria-live="assertive" aria-atomic="true"></div> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10