[{"data":1,"prerenderedAt":754},["ShallowReactive",2],{"/en-us/blog/vue-big-plan":3,"navigation-en-us":32,"banner-en-us":460,"footer-en-us":477,"Jacob Schatz":722,"next-steps-en-us":734,"footer-source-/en-us/blog/vue-big-plan/":749},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":22,"_id":25,"_type":26,"title":27,"_source":28,"_file":29,"_stem":30,"_extension":31},"/en-us/blog/vue-big-plan","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Our big Frontend plan revealed","Our long term plan to make GitLab as fast and performant as possible with Vue and webpack.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749683983/Blog/Hero%20Images/vue-big-plan-cover.png","https://about.gitlab.com/blog/vue-big-plan","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Our big Frontend plan revealed\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Jacob Schatz\"}],\n        \"datePublished\": \"2017-02-06\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21},[18],"Jacob Schatz","2017-02-06","The Frontend at GitLab is getting better and better every day. Today we did\ntwo big things, and I'd like to share them with you and our big plans for\nthe future.\n\n\n\u003C!--more-->\n\n\n\u003Cblockquote style=\"color: red\">\n\n\u003Cul>\n  \u003Cli>If you use the GDK, then make sure you update it! If you have no idea what I am talking about, then just keep reading.\u003C/li>\n  \u003Cli>Please see the \u003Ca href='https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/update-gdk.md'>documentation\u003C/a> for instructions on updating your GDK.\u003C/li>\n  \u003Cli>Please see our \u003Ca href='https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/troubleshooting.md#webpack'>troubleshooting guide\u003C/a> for any issues when updating your GDK.\u003C/li>\n  \u003Cli>Feel free to \u003Ca href='https://gitlab.com/gitlab-org/gitlab-ce/issues/new'>report\u003C/a> any additional issues you find.\u003C/li>\n\u003C/ul>\n\n\u003C/blockquote>\n\n\n## Our big Frontend plan\n\n\n[Vue](https://vuejs.org/) is awesome. I wrote an article a while ago that\nshowed [GitLab's love for Vue](/blog/why-we-chose-vue/). Today's article is\na way to show our plan over the long term to make GitLab as fast and\nperformant as possible with Vue and webpack. We want to make GitLab the\neasiest to develop for Frontend Developers.\n\n\nOne of the lessons I live by is \"It's not _always_ about the tools you use,\nbut **how** you use them.\"  Saying \"we chose Vue\", does not imply success.\nThis also means that we could be using Angular or React and have just as\nawesome of a product. Vue is simply the way there.\n\n\nHow do we plan to use Vue over the long run to make GitLab better, faster,\neasier and more awesome?\n\n\nThe plan below is a work in progress and very ambitious, but I believe that\nit will result in a much better frontend for development and performance.\nThis document is also a reference to myself of the things we plan to do here\nat GitLab's Frontend.\n\n\n## A healthier Frontend\n\n\nWhen I started at GitLab, our stack was (oversimplifying here) Rails with\njQuery. It hasn't changed much big picture wise except for Vue. Smaller\npicture, we've added many linters, better code coverage, and many other\ngreat things.\n\n\n### 1. Rewrite only what you need to\n\n\nWe are not rewriting GitLab's frontend entirely in Vue. That would be a very\nbad idea. It's not a bad idea for everyone, but it's a bad idea for a\nstartup. It would cost a tremendous amount of time and money. The existing\njQuery code (although some say is uncool) has been tested and works very\nwell. There is no need to rewrite functionality that works well, unless\nthere is going to be a major gain.\n\n\nWe also aren't writing every new thing in Vue. You do not need to do this\neither. But, it would be hard to find some part of the UI that would not\nbenefit from even the simplest parts of Vue.\n\n\nExamples of this are:\n\n\n1. The issue page (which shows an individual issue), has a lot of jQuery on\nit. We won't rewrite now, because it works well. We will rewrite small parts\nin Vue once we make certain features more real-time. We are currently making\nthe title and description real time.\n\n\n1. The [Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.html), which\n[Phil](https://twitter.com/iamphill) wrote, was a perfect candidate for Vue.\nIt was a brand new feature and had lots of reactive parts.\n\n\n1. The current issue page loads all comments at once and adds lots of event\nlisteners to the page. This page could benefit from Vue for performance\nreasons. We could make the comment section a Vue app and make the comments a\ncomponent with the emoji picker as components as well, etc. While we're in\nthere, we'll amp up the UX by allowing you to see the comment you linked to\nimmediately without waiting. There are better ways to show massive amounts\nof comments so we have to potentially rethink that.\n\n\n1. The pipelines page rewritten in vue for the arrival of real time\nupdating.\n\n\n1. The environments was written in Vue.\n\n\n1. There are many other places where we will be using Vue in the future and\nwhere we are already using Vue. Too many to list here.\n\n\nAs you can see, we won't just slap Vue on everything.\n\n\n### 2. Add in webpack\n\n\nRails has this awesome system of grabbing your Ruby libraries and bundling\nthem into your app. `bundle install` will install all the stuff you need\nfrom your `Gemfile`. So why does Frontend have to stick all their libraries\nin the `vendor` directory? Are we not on point enough to have our own\nlibrary delivery system? The javascript ecosystem has matured since the\nasset pipeline first arrived, and we now have `npm install` and advanced\ncode bundling tools that we can take advantage of.\n\n\nBy [introducing webpack into the equation (merged and ready for\naction!)](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7288) we\ngain multiple benefits.\n\n\n1. Javascript libraries aren't being bundled directly with the [GitLab\nsource code](/solutions/source-code-management/) or included\nwithin gem wrappers. e.g. `jquery-ui` or `bootstrap-rails` are included as a\nruby gem and we are at the mercy of the gem maintainer to keep the\nJavascript library up to date.\n\n1. When code is shared between files, we can make sure we don't load\n[lodash](https://lodash.com/) twice, for example. If both files load lodash,\nwe should only load the code for lodash once. Not only will lodash not be\nincluded twice, but with [tree\nshaking](https://webpack.js.org/guides/tree-shaking/) only the components of\nlodash that we use will be included rather than the whole library.\n\n1. We can add [hot module\nreplacement](https://webpack.js.org/concepts/hot-module-replacement/) to\nmake our Vue development quicker. This is a development bonus, as our\ncurrent development takes loads of time to refresh the page while developing\nGitLab. Spicy!\n\n1. We can now manage our dependencies properly. This should help a lot of\nfrontenders to contribute to GitLab. Devs won't need to figure out the whole\nRails Javascript situation in order to contribute. We can also dictate\nmanually what we want to include.\n\n1. SVGs are going to be huge.\n    1. [webpack](https://webpack.js.org/) bundles SVGs directly into our Javascript.\n    1. Right now, SVGs live in a specific directory in Rails. We use Rails helpers to pull in SVGs. With webpack we can pull in SVGs one at a time because webpack precompiles assets.\n    1. We won't have to fetch SVGs with an HTTP request.\n    1. We don't have to do tricky HTML hidden elements which is technical debt.\n    1. We don't have to mess around with SVGs in CSS. You cannot change the color of SVGs in CSS.\n1. We use a lot of Ruby to solve Javascript and CSS problems. Now we can\nsolve those problems on our own using only frontend tools.\n\n1. Using webpack's\n[CommonsChunkPlugin](https://webpack.js.org/plugins/commons-chunk-plugin/)\nwe split all of our common vendor libraries into their own separate file.\nSince these change very infrequently, they can stay cached for a much longer\nperiod of time.\n\n1. With webpack's [code\nsplitting](https://webpack.js.org/guides/code-splitting/) feature you can\nload just the JS you need to boot. Then you do a `require.ensure()` or\n`System.import()`. With this, we can tell webpack to request only exact JS\nyou need. It keeps the size of the file really small. For example if you\nhave `modal.js` for modals. If someone never uses the modals the code never\nloads. As soon as someone opens a modal, the JS gets loaded on demand.\n\n1. We can now properly manage our global scope. We can now do a `import x\nfrom y` instead of having our scripts pollute the global scope and pass\nclasses around on `window.gl.lol`.\n\n1. We can slim down the our Vue bundles because we can precompile templates\nand omit the template compiler from our production code. [Evan\nYou](https://twitter.com/youyuxi) (the creator of VueJS) explains this in\nthe [feature overview for Vue\n2.0](https://github.com/vuejs/vue/issues/2873):\n  > There will be two different builds:\n  > - Standalone build: includes both the compiler and the runtime. ...\n  > - Runtime only build: since it doesn't include the compiler, you need to either pre-compiled templates in a compile step, or manually written render functions.\n\n\n### 3. Remove Turbolinks\n\n\nWe used [TurboLinks](https://github.com/turbolinks/turbolinks) in GitLab,\nbut we've recently [removed\nit](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8570) with the\nlinked merge request, merged on 2017/02/03.\n\n\n#### What does Turbolinks achieve?\n\n\nWith TurboLinks, clicking a link won't navigate to a new page in the default\nbrowser `GET` request way. Instead, Turbolinks will replace the `body` tag\nof your app with the new content. All your Javascript is loaded one time,\nwhen using the asset pipeline. This usually only loads some small HTML and\nJavaScript. On GitLab, our pages would load an average of 20kb on each page\nload versus the full JavaScript file size of 800kb+. Turbolinks is a great\nsolution for many projects. When you start introducing slightly more complex\nJavascript it becomes a pain.\n\nWe did speed tests on pages with Turbolinks and without Turbolinks and we\nfound that the pages without Turbolinks performed better. We discovered that\nTurbolinks works well when you don't have a lot of event listeners to\nmanage. To add to this, we will be able to make our pages even faster in the\nfuture because we will divide the Javascript up between pages better with\nthe help of webpack. We were previously writing a lot of extra code to\nhandle all of Turbolink's problems and we can remove that code now.\n\n\n#### The problem we need to solve\n\n\nWhen your JS is loaded one time for multiple pages, events become a major\nproblem. If you are using `gem 'jquery-turbolinks'` as we are, then the `$`\n`ready` function will fire on every page load even though the page isn't\nloading in the traditional sense. It's painful to write page specific\nJavascript without including it for the whole app. We do it and it's fine,\nbut, why? There really isn't a reason for a lot of our JS that needs to be\nincluded on every page.\n\n\nAny external links do load faster so, we need to be careful about\nperformance.\n\n\nIf you aren't careful, your events will get loaded multiple times and thus\nfire multiple times. For example, take the following code:\n\n\n```js\n\n$(function(){\n  $(document).on('click','.some-element', function(){\n    console.log('Click loaded');\n  }\n});\n\n```\n\n\nThat click event will be loaded on every page and thus fire multiple times\nevery time `.some-element` is clicked.\n\n\n#### The Solutions\n\nThere are a few remedies to this problem. Some are good and some are bad.\n\n\n1. Don't create events in `$` `ready` callbacks.\n\n2. Use the following stinky solution:\n\n    ```js\n    $(document)\n    .off('click', '.some-element')\n    .on('click'...\n    ```\n\n     I call this the `die live` method. Old jQuery code people use to write `die().live()` everywhere. That's the old school jQuery `off().on()`.\n3. Write an event manager to be a delegate for all added events.\n\n4. [Remove\nTurbolinks](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8570) and\nmake sure you load only the code you need on each page.\n\n\nI am opting for option 4, in order to make our development lives easier and\nget multiple performance gains.\n\n\n#### The Bonus\n\n\nAfter we remove Turbolinks we can do something really cool. We can have each\npage live on its own. Then, certain pages can be their own Vue apps. For\nexample, we can make the file browser its own Vue application. The merge\nrequest page can be its own application. The code for the file viewer won't\nneed to be loaded on any other page and the same goes for other pages. This\nis not anything new, this is just basic web development. This is also not a\nnew paradigm, and we would not be the first.\n\n\n## Conclusion\n\nThere is the argument for making the whole site a single page application,\nbut I think this would just be the hardest to maintain and has zero benefits\nfor the performance and the user. Also, there's a higher chance of making\nGitLab a janky app. For example, the profile page could be potentially very\nlight, and there would be no reason for that if someone is linked directly\nto the profile page; it should load every single piece of Javascript in our\nproject.\n\n\nThis is just one small step for GitLab and one giant leap for the frontend\nteam. In the future you will see many new cool things coming from our team.\nThis move was one step in that direction.\n\n\nQuestions, suggestions, ideas? Please leave a comment\n\nbelow or tweet at us [@GitLab](https://twitter.com/gitlab)!\n","engineering",{"slug":23,"featured":6,"template":24},"vue-big-plan","BlogPost","content:en-us:blog:vue-big-plan.yml","yaml","Vue Big Plan","content","en-us/blog/vue-big-plan.yml","en-us/blog/vue-big-plan","yml",{"_path":33,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"data":35,"_id":456,"_type":26,"title":457,"_source":28,"_file":458,"_stem":459,"_extension":31},"/shared/en-us/main-navigation","en-us",{"logo":36,"freeTrial":41,"sales":46,"login":51,"items":56,"search":387,"minimal":418,"duo":437,"pricingDeployment":446},{"config":37},{"href":38,"dataGaName":39,"dataGaLocation":40},"/","gitlab logo","header",{"text":42,"config":43},"Get free trial",{"href":44,"dataGaName":45,"dataGaLocation":40},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":47,"config":48},"Talk to sales",{"href":49,"dataGaName":50,"dataGaLocation":40},"/sales/","sales",{"text":52,"config":53},"Sign in",{"href":54,"dataGaName":55,"dataGaLocation":40},"https://gitlab.com/users/sign_in/","sign in",[57,101,198,203,308,368],{"text":58,"config":59,"cards":61,"footer":84},"Platform",{"dataNavLevelOne":60},"platform",[62,68,76],{"title":58,"description":63,"link":64},"The most comprehensive AI-powered DevSecOps Platform",{"text":65,"config":66},"Explore our Platform",{"href":67,"dataGaName":60,"dataGaLocation":40},"/platform/",{"title":69,"description":70,"link":71},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":72,"config":73},"Meet GitLab Duo",{"href":74,"dataGaName":75,"dataGaLocation":40},"/gitlab-duo/","gitlab duo ai",{"title":77,"description":78,"link":79},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":80,"config":81},"Learn more",{"href":82,"dataGaName":83,"dataGaLocation":40},"/why-gitlab/","why gitlab",{"title":85,"items":86},"Get started with",[87,92,97],{"text":88,"config":89},"Platform Engineering",{"href":90,"dataGaName":91,"dataGaLocation":40},"/solutions/platform-engineering/","platform engineering",{"text":93,"config":94},"Developer Experience",{"href":95,"dataGaName":96,"dataGaLocation":40},"/developer-experience/","Developer experience",{"text":98,"config":99},"MLOps",{"href":100,"dataGaName":98,"dataGaLocation":40},"/topics/devops/the-role-of-ai-in-devops/",{"text":102,"left":103,"config":104,"link":106,"lists":110,"footer":180},"Product",true,{"dataNavLevelOne":105},"solutions",{"text":107,"config":108},"View all Solutions",{"href":109,"dataGaName":105,"dataGaLocation":40},"/solutions/",[111,136,159],{"title":112,"description":113,"link":114,"items":119},"Automation","CI/CD and automation to accelerate deployment",{"config":115},{"icon":116,"href":117,"dataGaName":118,"dataGaLocation":40},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[120,124,128,132],{"text":121,"config":122},"CI/CD",{"href":123,"dataGaLocation":40,"dataGaName":121},"/solutions/continuous-integration/",{"text":125,"config":126},"AI-Assisted Development",{"href":74,"dataGaLocation":40,"dataGaName":127},"AI assisted development",{"text":129,"config":130},"Source Code Management",{"href":131,"dataGaLocation":40,"dataGaName":129},"/solutions/source-code-management/",{"text":133,"config":134},"Automated Software Delivery",{"href":117,"dataGaLocation":40,"dataGaName":135},"Automated software delivery",{"title":137,"description":138,"link":139,"items":144},"Security","Deliver code faster without compromising security",{"config":140},{"href":141,"dataGaName":142,"dataGaLocation":40,"icon":143},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[145,149,154],{"text":146,"config":147},"Application Security Testing",{"href":141,"dataGaName":148,"dataGaLocation":40},"Application security testing",{"text":150,"config":151},"Software Supply Chain Security",{"href":152,"dataGaLocation":40,"dataGaName":153},"/solutions/supply-chain/","Software supply chain security",{"text":155,"config":156},"Software Compliance",{"href":157,"dataGaName":158,"dataGaLocation":40},"/solutions/software-compliance/","software compliance",{"title":160,"link":161,"items":166},"Measurement",{"config":162},{"icon":163,"href":164,"dataGaName":165,"dataGaLocation":40},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[167,171,175],{"text":168,"config":169},"Visibility & Measurement",{"href":164,"dataGaLocation":40,"dataGaName":170},"Visibility and Measurement",{"text":172,"config":173},"Value Stream Management",{"href":174,"dataGaLocation":40,"dataGaName":172},"/solutions/value-stream-management/",{"text":176,"config":177},"Analytics & Insights",{"href":178,"dataGaLocation":40,"dataGaName":179},"/solutions/analytics-and-insights/","Analytics and insights",{"title":181,"items":182},"GitLab for",[183,188,193],{"text":184,"config":185},"Enterprise",{"href":186,"dataGaLocation":40,"dataGaName":187},"/enterprise/","enterprise",{"text":189,"config":190},"Small Business",{"href":191,"dataGaLocation":40,"dataGaName":192},"/small-business/","small business",{"text":194,"config":195},"Public Sector",{"href":196,"dataGaLocation":40,"dataGaName":197},"/solutions/public-sector/","public sector",{"text":199,"config":200},"Pricing",{"href":201,"dataGaName":202,"dataGaLocation":40,"dataNavLevelOne":202},"/pricing/","pricing",{"text":204,"config":205,"link":207,"lists":211,"feature":295},"Resources",{"dataNavLevelOne":206},"resources",{"text":208,"config":209},"View all resources",{"href":210,"dataGaName":206,"dataGaLocation":40},"/resources/",[212,245,267],{"title":213,"items":214},"Getting started",[215,220,225,230,235,240],{"text":216,"config":217},"Install",{"href":218,"dataGaName":219,"dataGaLocation":40},"/install/","install",{"text":221,"config":222},"Quick start guides",{"href":223,"dataGaName":224,"dataGaLocation":40},"/get-started/","quick setup checklists",{"text":226,"config":227},"Learn",{"href":228,"dataGaLocation":40,"dataGaName":229},"https://university.gitlab.com/","learn",{"text":231,"config":232},"Product documentation",{"href":233,"dataGaName":234,"dataGaLocation":40},"https://docs.gitlab.com/","product documentation",{"text":236,"config":237},"Best practice videos",{"href":238,"dataGaName":239,"dataGaLocation":40},"/getting-started-videos/","best practice videos",{"text":241,"config":242},"Integrations",{"href":243,"dataGaName":244,"dataGaLocation":40},"/integrations/","integrations",{"title":246,"items":247},"Discover",[248,253,257,262],{"text":249,"config":250},"Customer success stories",{"href":251,"dataGaName":252,"dataGaLocation":40},"/customers/","customer success stories",{"text":254,"config":255},"Blog",{"href":256,"dataGaName":5,"dataGaLocation":40},"/blog/",{"text":258,"config":259},"Remote",{"href":260,"dataGaName":261,"dataGaLocation":40},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":263,"config":264},"TeamOps",{"href":265,"dataGaName":266,"dataGaLocation":40},"/teamops/","teamops",{"title":268,"items":269},"Connect",[270,275,280,285,290],{"text":271,"config":272},"GitLab Services",{"href":273,"dataGaName":274,"dataGaLocation":40},"/services/","services",{"text":276,"config":277},"Community",{"href":278,"dataGaName":279,"dataGaLocation":40},"/community/","community",{"text":281,"config":282},"Forum",{"href":283,"dataGaName":284,"dataGaLocation":40},"https://forum.gitlab.com/","forum",{"text":286,"config":287},"Events",{"href":288,"dataGaName":289,"dataGaLocation":40},"/events/","events",{"text":291,"config":292},"Partners",{"href":293,"dataGaName":294,"dataGaLocation":40},"/partners/","partners",{"backgroundColor":296,"textColor":297,"text":298,"image":299,"link":303},"#2f2a6b","#fff","Insights for the future of software development",{"altText":300,"config":301},"the source promo card",{"src":302},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":304,"config":305},"Read the latest",{"href":306,"dataGaName":307,"dataGaLocation":40},"/the-source/","the source",{"text":309,"config":310,"lists":312},"Company",{"dataNavLevelOne":311},"company",[313],{"items":314},[315,320,326,328,333,338,343,348,353,358,363],{"text":316,"config":317},"About",{"href":318,"dataGaName":319,"dataGaLocation":40},"/company/","about",{"text":321,"config":322,"footerGa":325},"Jobs",{"href":323,"dataGaName":324,"dataGaLocation":40},"/jobs/","jobs",{"dataGaName":324},{"text":286,"config":327},{"href":288,"dataGaName":289,"dataGaLocation":40},{"text":329,"config":330},"Leadership",{"href":331,"dataGaName":332,"dataGaLocation":40},"/company/team/e-group/","leadership",{"text":334,"config":335},"Team",{"href":336,"dataGaName":337,"dataGaLocation":40},"/company/team/","team",{"text":339,"config":340},"Handbook",{"href":341,"dataGaName":342,"dataGaLocation":40},"https://handbook.gitlab.com/","handbook",{"text":344,"config":345},"Investor relations",{"href":346,"dataGaName":347,"dataGaLocation":40},"https://ir.gitlab.com/","investor relations",{"text":349,"config":350},"Trust Center",{"href":351,"dataGaName":352,"dataGaLocation":40},"/security/","trust center",{"text":354,"config":355},"AI Transparency Center",{"href":356,"dataGaName":357,"dataGaLocation":40},"/ai-transparency-center/","ai transparency center",{"text":359,"config":360},"Newsletter",{"href":361,"dataGaName":362,"dataGaLocation":40},"/company/contact/","newsletter",{"text":364,"config":365},"Press",{"href":366,"dataGaName":367,"dataGaLocation":40},"/press/","press",{"text":369,"config":370,"lists":371},"Contact us",{"dataNavLevelOne":311},[372],{"items":373},[374,377,382],{"text":47,"config":375},{"href":49,"dataGaName":376,"dataGaLocation":40},"talk to sales",{"text":378,"config":379},"Support portal",{"href":380,"dataGaName":381,"dataGaLocation":40},"https://support.gitlab.com","support portal",{"text":383,"config":384},"Customer portal",{"href":385,"dataGaName":386,"dataGaLocation":40},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":388,"login":389,"suggestions":396},"Close",{"text":390,"link":391},"To search repositories and projects, login to",{"text":392,"config":393},"gitlab.com",{"href":54,"dataGaName":394,"dataGaLocation":395},"search login","search",{"text":397,"default":398},"Suggestions",[399,401,405,407,411,415],{"text":69,"config":400},{"href":74,"dataGaName":69,"dataGaLocation":395},{"text":402,"config":403},"Code Suggestions (AI)",{"href":404,"dataGaName":402,"dataGaLocation":395},"/solutions/code-suggestions/",{"text":121,"config":406},{"href":123,"dataGaName":121,"dataGaLocation":395},{"text":408,"config":409},"GitLab on AWS",{"href":410,"dataGaName":408,"dataGaLocation":395},"/partners/technology-partners/aws/",{"text":412,"config":413},"GitLab on Google Cloud",{"href":414,"dataGaName":412,"dataGaLocation":395},"/partners/technology-partners/google-cloud-platform/",{"text":416,"config":417},"Why GitLab?",{"href":82,"dataGaName":416,"dataGaLocation":395},{"freeTrial":419,"mobileIcon":424,"desktopIcon":429,"secondaryButton":432},{"text":420,"config":421},"Start free trial",{"href":422,"dataGaName":45,"dataGaLocation":423},"https://gitlab.com/-/trials/new/","nav",{"altText":425,"config":426},"Gitlab Icon",{"src":427,"dataGaName":428,"dataGaLocation":423},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":425,"config":430},{"src":431,"dataGaName":428,"dataGaLocation":423},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":433,"config":434},"Get Started",{"href":435,"dataGaName":436,"dataGaLocation":423},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":438,"mobileIcon":442,"desktopIcon":444},{"text":439,"config":440},"Learn more about GitLab Duo",{"href":74,"dataGaName":441,"dataGaLocation":423},"gitlab duo",{"altText":425,"config":443},{"src":427,"dataGaName":428,"dataGaLocation":423},{"altText":425,"config":445},{"src":431,"dataGaName":428,"dataGaLocation":423},{"freeTrial":447,"mobileIcon":452,"desktopIcon":454},{"text":448,"config":449},"Back to pricing",{"href":201,"dataGaName":450,"dataGaLocation":423,"icon":451},"back to pricing","GoBack",{"altText":425,"config":453},{"src":427,"dataGaName":428,"dataGaLocation":423},{"altText":425,"config":455},{"src":431,"dataGaName":428,"dataGaLocation":423},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":461,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"title":462,"button":463,"image":468,"config":472,"_id":474,"_type":26,"_source":28,"_file":475,"_stem":476,"_extension":31},"/shared/en-us/banner","is now in public beta!",{"text":464,"config":465},"Try the Beta",{"href":466,"dataGaName":467,"dataGaLocation":40},"/gitlab-duo/agent-platform/","duo banner",{"altText":469,"config":470},"GitLab Duo Agent Platform",{"src":471},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":473},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":478,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"data":479,"_id":718,"_type":26,"title":719,"_source":28,"_file":720,"_stem":721,"_extension":31},"/shared/en-us/main-footer",{"text":480,"source":481,"edit":487,"contribute":492,"config":497,"items":502,"minimal":710},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":482,"config":483},"View page source",{"href":484,"dataGaName":485,"dataGaLocation":486},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":488,"config":489},"Edit this page",{"href":490,"dataGaName":491,"dataGaLocation":486},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":493,"config":494},"Please contribute",{"href":495,"dataGaName":496,"dataGaLocation":486},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":498,"facebook":499,"youtube":500,"linkedin":501},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[503,550,603,647,676],{"title":199,"links":504,"subMenu":519},[505,509,514],{"text":506,"config":507},"View plans",{"href":201,"dataGaName":508,"dataGaLocation":486},"view plans",{"text":510,"config":511},"Why Premium?",{"href":512,"dataGaName":513,"dataGaLocation":486},"/pricing/premium/","why premium",{"text":515,"config":516},"Why Ultimate?",{"href":517,"dataGaName":518,"dataGaLocation":486},"/pricing/ultimate/","why ultimate",[520],{"title":521,"links":522},"Contact Us",[523,526,528,530,535,540,545],{"text":524,"config":525},"Contact sales",{"href":49,"dataGaName":50,"dataGaLocation":486},{"text":378,"config":527},{"href":380,"dataGaName":381,"dataGaLocation":486},{"text":383,"config":529},{"href":385,"dataGaName":386,"dataGaLocation":486},{"text":531,"config":532},"Status",{"href":533,"dataGaName":534,"dataGaLocation":486},"https://status.gitlab.com/","status",{"text":536,"config":537},"Terms of use",{"href":538,"dataGaName":539,"dataGaLocation":486},"/terms/","terms of use",{"text":541,"config":542},"Privacy statement",{"href":543,"dataGaName":544,"dataGaLocation":486},"/privacy/","privacy statement",{"text":546,"config":547},"Cookie preferences",{"dataGaName":548,"dataGaLocation":486,"id":549,"isOneTrustButton":103},"cookie preferences","ot-sdk-btn",{"title":102,"links":551,"subMenu":559},[552,556],{"text":553,"config":554},"DevSecOps platform",{"href":67,"dataGaName":555,"dataGaLocation":486},"devsecops platform",{"text":125,"config":557},{"href":74,"dataGaName":558,"dataGaLocation":486},"ai-assisted development",[560],{"title":561,"links":562},"Topics",[563,568,573,578,583,588,593,598],{"text":564,"config":565},"CICD",{"href":566,"dataGaName":567,"dataGaLocation":486},"/topics/ci-cd/","cicd",{"text":569,"config":570},"GitOps",{"href":571,"dataGaName":572,"dataGaLocation":486},"/topics/gitops/","gitops",{"text":574,"config":575},"DevOps",{"href":576,"dataGaName":577,"dataGaLocation":486},"/topics/devops/","devops",{"text":579,"config":580},"Version Control",{"href":581,"dataGaName":582,"dataGaLocation":486},"/topics/version-control/","version control",{"text":584,"config":585},"DevSecOps",{"href":586,"dataGaName":587,"dataGaLocation":486},"/topics/devsecops/","devsecops",{"text":589,"config":590},"Cloud Native",{"href":591,"dataGaName":592,"dataGaLocation":486},"/topics/cloud-native/","cloud native",{"text":594,"config":595},"AI for Coding",{"href":596,"dataGaName":597,"dataGaLocation":486},"/topics/devops/ai-for-coding/","ai for coding",{"text":599,"config":600},"Agentic AI",{"href":601,"dataGaName":602,"dataGaLocation":486},"/topics/agentic-ai/","agentic ai",{"title":604,"links":605},"Solutions",[606,608,610,615,619,622,626,629,631,634,637,642],{"text":146,"config":607},{"href":141,"dataGaName":146,"dataGaLocation":486},{"text":135,"config":609},{"href":117,"dataGaName":118,"dataGaLocation":486},{"text":611,"config":612},"Agile development",{"href":613,"dataGaName":614,"dataGaLocation":486},"/solutions/agile-delivery/","agile delivery",{"text":616,"config":617},"SCM",{"href":131,"dataGaName":618,"dataGaLocation":486},"source code management",{"text":564,"config":620},{"href":123,"dataGaName":621,"dataGaLocation":486},"continuous integration & delivery",{"text":623,"config":624},"Value stream management",{"href":174,"dataGaName":625,"dataGaLocation":486},"value stream management",{"text":569,"config":627},{"href":628,"dataGaName":572,"dataGaLocation":486},"/solutions/gitops/",{"text":184,"config":630},{"href":186,"dataGaName":187,"dataGaLocation":486},{"text":632,"config":633},"Small business",{"href":191,"dataGaName":192,"dataGaLocation":486},{"text":635,"config":636},"Public sector",{"href":196,"dataGaName":197,"dataGaLocation":486},{"text":638,"config":639},"Education",{"href":640,"dataGaName":641,"dataGaLocation":486},"/solutions/education/","education",{"text":643,"config":644},"Financial services",{"href":645,"dataGaName":646,"dataGaLocation":486},"/solutions/finance/","financial services",{"title":204,"links":648},[649,651,653,655,658,660,662,664,666,668,670,672,674],{"text":216,"config":650},{"href":218,"dataGaName":219,"dataGaLocation":486},{"text":221,"config":652},{"href":223,"dataGaName":224,"dataGaLocation":486},{"text":226,"config":654},{"href":228,"dataGaName":229,"dataGaLocation":486},{"text":231,"config":656},{"href":233,"dataGaName":657,"dataGaLocation":486},"docs",{"text":254,"config":659},{"href":256,"dataGaName":5,"dataGaLocation":486},{"text":249,"config":661},{"href":251,"dataGaName":252,"dataGaLocation":486},{"text":258,"config":663},{"href":260,"dataGaName":261,"dataGaLocation":486},{"text":271,"config":665},{"href":273,"dataGaName":274,"dataGaLocation":486},{"text":263,"config":667},{"href":265,"dataGaName":266,"dataGaLocation":486},{"text":276,"config":669},{"href":278,"dataGaName":279,"dataGaLocation":486},{"text":281,"config":671},{"href":283,"dataGaName":284,"dataGaLocation":486},{"text":286,"config":673},{"href":288,"dataGaName":289,"dataGaLocation":486},{"text":291,"config":675},{"href":293,"dataGaName":294,"dataGaLocation":486},{"title":309,"links":677},[678,680,682,684,686,688,690,694,699,701,703,705],{"text":316,"config":679},{"href":318,"dataGaName":311,"dataGaLocation":486},{"text":321,"config":681},{"href":323,"dataGaName":324,"dataGaLocation":486},{"text":329,"config":683},{"href":331,"dataGaName":332,"dataGaLocation":486},{"text":334,"config":685},{"href":336,"dataGaName":337,"dataGaLocation":486},{"text":339,"config":687},{"href":341,"dataGaName":342,"dataGaLocation":486},{"text":344,"config":689},{"href":346,"dataGaName":347,"dataGaLocation":486},{"text":691,"config":692},"Sustainability",{"href":693,"dataGaName":691,"dataGaLocation":486},"/sustainability/",{"text":695,"config":696},"Diversity, inclusion and belonging (DIB)",{"href":697,"dataGaName":698,"dataGaLocation":486},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":349,"config":700},{"href":351,"dataGaName":352,"dataGaLocation":486},{"text":359,"config":702},{"href":361,"dataGaName":362,"dataGaLocation":486},{"text":364,"config":704},{"href":366,"dataGaName":367,"dataGaLocation":486},{"text":706,"config":707},"Modern Slavery Transparency Statement",{"href":708,"dataGaName":709,"dataGaLocation":486},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":711},[712,714,716],{"text":536,"config":713},{"href":538,"dataGaName":539,"dataGaLocation":486},{"text":541,"config":715},{"href":543,"dataGaName":544,"dataGaLocation":486},{"text":546,"config":717},{"dataGaName":548,"dataGaLocation":486,"id":549,"isOneTrustButton":103},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[723],{"_path":724,"_dir":725,"_draft":6,"_partial":6,"_locale":7,"content":726,"config":729,"_id":731,"_type":26,"title":18,"_source":28,"_file":732,"_stem":733,"_extension":31},"/en-us/blog/authors/jacob-schatz","authors",{"name":18,"config":727},{"headshot":7,"ctfId":728},"jschatz1",{"template":730},"BlogAuthor","content:en-us:blog:authors:jacob-schatz.yml","en-us/blog/authors/jacob-schatz.yml","en-us/blog/authors/jacob-schatz",{"_path":735,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"header":736,"eyebrow":737,"blurb":738,"button":739,"secondaryButton":743,"_id":745,"_type":26,"title":746,"_source":28,"_file":747,"_stem":748,"_extension":31},"/shared/en-us/next-steps","Start shipping better software faster","50%+ of the Fortune 100 trust GitLab","See what your team can do with the intelligent\n\n\nDevSecOps platform.\n",{"text":42,"config":740},{"href":741,"dataGaName":45,"dataGaLocation":742},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":47,"config":744},{"href":49,"dataGaName":50,"dataGaLocation":742},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":750,"content":751,"config":753,"_id":25,"_type":26,"title":27,"_source":28,"_file":29,"_stem":30,"_extension":31},{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},{"title":9,"description":10,"authors":752,"heroImage":11,"date":19,"body":20,"category":21},[18],{"slug":23,"featured":6,"template":24},1761814440464]