[{"data":1,"prerenderedAt":757},["ShallowReactive",2],{"/en-us/blog/serverless-js-project-template":3,"navigation-en-us":36,"banner-en-us":463,"footer-en-us":480,"Mike Greiling":724,"next-steps-en-us":736,"footer-source-/en-us/blog/serverless-js-project-template/":751},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":26,"_id":29,"_type":30,"title":31,"_source":32,"_file":33,"_stem":34,"_extension":35},"/en-us/blog/serverless-js-project-template","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Starting a serverless JS project with GitLab","Introduction to the new serverless JS project template at GitLab","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680997/Blog/Hero%20Images/clouds-cover.jpg","https://about.gitlab.com/blog/serverless-js-project-template","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Starting a serverless JS project with GitLab\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Mike Greiling\"}],\n        \"datePublished\": \"2020-01-14\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21,"tags":22},[18],"Mike Greiling","2020-01-14","{::options parse_block_html=\"true\" /}\n\n\n\n\n\u003C!-- Content start here -->\n\n\nIf you've been working in web development these past few years than you've\nno doubt heard about [serverless](/topics/serverless/) FaaS solutions like\nAWS Lambda or Knative. The idea boils down to writing code as a set of\ndiscrete functions that can be triggered by events. All worries about\nprovisioning server nodes, scaling them, managing your back-end stack, and\nmany other operational tasks are abstracted away. Moreover, it often results\nin massive cost savings as compute resources are provisioned on-demand. As\nthis paradigm is growing in maturity and popularity, many tools have been\ncreated to make the process even easier and there has never been a better\ntime to try it out for yourself.\n\n\nTo demonstrate how easy it is to get started with FaaS in GitLab, we've now\nadded a project template to get you up and running even faster. If you're\ninterested in wading into the serverless waters without running a single\ncommand in your terminal, follow along and try it yourself! All that is\nneeded for this example is a free GitLab account and an AWS account.\n\n\n### 1. Creating a project\n\n\nTo start off, let's create a project with our new serverless template. Open\nup the [new project](https://gitlab.com/projects/new) page and select the\n\"Create from template\" tab. Then scroll down and select the \"Serverless\nFramework/JS\" template.\n\n\n![Step\n1](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-1.1.jpg){:\n.shadow.medium.center}\n\n\nGive your project a name and select \"Create project\"\n\n\n### 2. Configuring your AWS credentials\n\n\nNow that we have our GitLab project complete with a boilerplate serverless\napplication, it's time to give it access credentials to AWS so we can deploy\nit.\n\n\nOpen up the AWS console, sign in, and navigate to the [IAM\nsection](https://console.aws.amazon.com/iam/home). Here you can select\n\"Users\" in the left-hand column, and create a new user using the \"Add user\"\nbutton at the top of the list.\n\n\n![Step\n2-1](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-2.1.jpg){:\n.shadow.medium.center}\n\n\nGive your user a name like \"gitlab-serverless\" and make sure to select the\n\"Programatic access\" checkbox before clicking on \"Next\".\n\n\n![Step\n2-2](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-2.2.jpg){:\n.shadow.medium.center}\n\n\nNow we need to give this user the appropriate permissions to deploy\nserverless functions. On the \"Permissions\" page select \"Attach existing\npolicies directly\" and then click the \"Create policy\" button. This will open\na new window.\n\n\n![Step\n2-3](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-2.3.jpg){:\n.shadow.medium.center}\n\n\nHere you'll need to select the \"JSON\" tab and paste the following policy\nstatement:\n\n\n```json\n\n{\n  \"Statement\": [\n    {\n      \"Action\": [\n        \"apigateway:*\",\n        \"cloudformation:CancelUpdateStack\",\n        \"cloudformation:ContinueUpdateRollback\",\n        \"cloudformation:CreateChangeSet\",\n        \"cloudformation:CreateStack\",\n        \"cloudformation:CreateUploadBucket\",\n        \"cloudformation:DeleteStack\",\n        \"cloudformation:Describe*\",\n        \"cloudformation:EstimateTemplateCost\",\n        \"cloudformation:ExecuteChangeSet\",\n        \"cloudformation:Get*\",\n        \"cloudformation:List*\",\n        \"cloudformation:PreviewStackUpdate\",\n        \"cloudformation:UpdateStack\",\n        \"cloudformation:UpdateTerminationProtection\",\n        \"cloudformation:ValidateTemplate\",\n        \"dynamodb:CreateTable\",\n        \"dynamodb:DeleteTable\",\n        \"dynamodb:DescribeTable\",\n        \"ec2:AttachInternetGateway\",\n        \"ec2:AuthorizeSecurityGroupIngress\",\n        \"ec2:CreateInternetGateway\",\n        \"ec2:CreateNetworkAcl\",\n        \"ec2:CreateNetworkAclEntry\",\n        \"ec2:CreateRouteTable\",\n        \"ec2:CreateSecurityGroup\",\n        \"ec2:CreateSubnet\",\n        \"ec2:CreateTags\",\n        \"ec2:CreateVpc\",\n        \"ec2:DeleteInternetGateway\",\n        \"ec2:DeleteNetworkAcl\",\n        \"ec2:DeleteNetworkAclEntry\",\n        \"ec2:DeleteRouteTable\",\n        \"ec2:DeleteSecurityGroup\",\n        \"ec2:DeleteSubnet\",\n        \"ec2:DeleteVpc\",\n        \"ec2:Describe*\",\n        \"ec2:DetachInternetGateway\",\n        \"ec2:ModifyVpcAttribute\",\n        \"events:DeleteRule\",\n        \"events:DescribeRule\",\n        \"events:ListRuleNamesByTarget\",\n        \"events:ListRules\",\n        \"events:ListTargetsByRule\",\n        \"events:PutRule\",\n        \"events:PutTargets\",\n        \"events:RemoveTargets\",\n        \"iam:CreateRole\",\n        \"iam:DeleteRole\",\n        \"iam:DeleteRolePolicy\",\n        \"iam:GetRole\",\n        \"iam:PassRole\",\n        \"iam:PutRolePolicy\",\n        \"iot:CreateTopicRule\",\n        \"iot:DeleteTopicRule\",\n        \"iot:DisableTopicRule\",\n        \"iot:EnableTopicRule\",\n        \"iot:ReplaceTopicRule\",\n        \"kinesis:CreateStream\",\n        \"kinesis:DeleteStream\",\n        \"kinesis:DescribeStream\",\n        \"lambda:*\",\n        \"logs:CreateLogGroup\",\n        \"logs:DeleteLogGroup\",\n        \"logs:DescribeLogGroups\",\n        \"logs:DescribeLogStreams\",\n        \"logs:FilterLogEvents\",\n        \"logs:GetLogEvents\",\n        \"s3:CreateBucket\",\n        \"s3:DeleteBucket\",\n        \"s3:DeleteBucketPolicy\",\n        \"s3:DeleteObject\",\n        \"s3:DeleteObjectVersion\",\n        \"s3:GetObject\",\n        \"s3:GetObjectVersion\",\n        \"s3:ListAllMyBuckets\",\n        \"s3:ListBucket\",\n        \"s3:PutBucketNotification\",\n        \"s3:PutBucketPolicy\",\n        \"s3:PutBucketTagging\",\n        \"s3:PutBucketWebsite\",\n        \"s3:PutEncryptionConfiguration\",\n        \"s3:PutObject\",\n        \"sns:CreateTopic\",\n        \"sns:DeleteTopic\",\n        \"sns:GetSubscriptionAttributes\",\n        \"sns:GetTopicAttributes\",\n        \"sns:ListSubscriptions\",\n        \"sns:ListSubscriptionsByTopic\",\n        \"sns:ListTopics\",\n        \"sns:SetSubscriptionAttributes\",\n        \"sns:SetTopicAttributes\",\n        \"sns:Subscribe\",\n        \"sns:Unsubscribe\",\n        \"states:CreateStateMachine\",\n        \"states:DeleteStateMachine\"\n      ],\n      \"Effect\": \"Allow\",\n      \"Resource\": \"*\"\n    }\n  ],\n  \"Version\": \"2012-10-17\"\n}\n\n```\n\n\n> Note: This policy is an example that encompasses pretty much everything\nthe Serverless framework _might_ need on AWS, but much of it not likely to\nbe used. You may wish to restrict this policy to fit your needs and security\nrequirements. At minimum, the serverless credentials will need access to the\n`cloudformation`, `iam`, `lambda`, `logs`, and `s3` functions specified\nabove.\n\n\n![Step\n2-4](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-2.4.jpg){:\n.shadow.medium.center}\n\n\nClick \"Review Policy\" and you'll need to give this policy a name. I've used\n\"GitLabServerlessPolicy\". Then click \"Create policy\".\n\n\nAfter this is done, return to your \"Add user\" tab and search for the policy\nyou just created (you may need to hit the \"refresh\" icon on the right).\nCheck the box next to this policy and select the \"Next\" button.\n\n\n![Step\n2-5](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-2.5.jpg){:\n.shadow.medium.center}\n\n\nProceed to add tags or skip straight to the review. The final page should\nresemble the following:\n\n\n![Step\n2-6](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-2.6.jpg){:\n.shadow.medium.center}\n\n\nAfter clicking \"Create user\" you should finally be presented with a page\nthat shows you your access credentials for this new AWS user account. Select\n\"show\" next to the \"secret access key\" and copy both this and the access key\nID someplace for safe keeping.\n\n\n### 3. Entering your AWS credentials\n\n\nReturning back to GitLab, we'll need to enter these two credentials into our\nproject's [CI/CD settings](/topics/ci-cd/). Select \"Settings -> CI/CD\" in\nthe left-hand menu.\n\n\n![Step\n3-1](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-3.1.jpg){:\n.shadow.small.center}\n\n\nOn this page, we need to expand the Variables section and enter our AWS\ncredentials:\n\n\n![Step\n3-2](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-3.2.jpg){:\n.shadow.medium.center}\n\n\nUse `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` as the keys for the two\nvalues you copied from AWS in the previous step. Don't forget to click \"Save\nvariables\".\n\n\n### 4. Deploying your first AWS Lambda function.\n\n\nNow it's time to deploy your serverless project. If you're doing this on\ngitlab.com you've already got access to a GitLab runner with 2,000 free CI\npipeline minutes, if not you'll need to [configure a runner\nyourself](https://docs.gitlab.com/runner/#install-gitlab-runner).\n\n\nGo to \"CI/CD -> Pipelines\" in the left-hand menu and click the \"Run\nPipeline\" button. For fun, let's enter an environment variable with the key\n`A_VARIABLE` and give it whatever value you want. This will be usable by our\ndeployed function.\n\n\n![Step\n4-1](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-4.1.jpg){:\n.shadow.medium.center}\n\n\nSelect \"Run Pipeline\" and you should see your jobs start running. This\nproject template has tests which will automatically run every time you run a\npipeline. Once those are complete, the \"production\" job will deploy your\ncode to AWS Lambda and finally it will produce a landing page on [GitLab\nPages](https://docs.gitlab.com/ee/user/project/pages/). After just\na few minutes this process should complete and you can visit \"Settings ->\nPages\" to see a link to the URL where your GitLab project has been deployed.\n(It may take a few minutes before this URL is accessible the first time you\nmake a deployment).\n\n\n![Step\n4-2](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-4.2.jpg){:\n.shadow.medium.center}\n\n\nWhen you visit this page, here's what you'll see:\n\n\n![Step 4\nResult](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-4.3.gif){:\n.shadow.medium.center}\n\n\nYou can enter an input value and click \"run function\". This input is sent to\nyour serverless function which then responds and the response is printed\nunder \"Function Output:\". Note that the environment value we provided using\nthe `A_VARIABLE` key is present as well.\n\n\n### 5. Making Changes\n\n\nNow that we have a working AWS serverless project, let's try to make our own\nfunction. How about a simple calculator?\n\n\nOpen up the Web IDE and let's make the following changes:\n\n\nWithin `src/handler.js` add the following function:\n\n\n```javascript\n\nmodule.exports.add = async function(event) {\n  const A = Number(event.queryStringParameters.A);\n  const B = Number(event.queryStringParameters.B);\n  const result = A + B;\n\n  return {\n    statusCode: 200,\n    headers: {\n      \"Access-Control-Allow-Origin\": \"*\"\n    },\n    body: result\n  };\n};\n\n```\n\n\nThen open `public/index.html` and replace it with:\n\n\n```html\n\n\u003C!DOCTYPE html>\n\n\u003Chtml>\n  \u003Chead>\n    \u003Ctitle>GitLab Serverless Framework example\u003C/title>\n  \u003C/head>\n  \u003Cbody>\n    \u003Ch3>Add two values:\u003C/h3>\n    \u003Clabel>A: \u003Cinput type=\"text\" id=\"inputA\" placeholder=\"0\" name=\"A\"/>\u003C/label>\n    \u003Clabel>B: \u003Cinput type=\"text\" id=\"inputB\" placeholder=\"0\" name=\"B\"/>\u003C/label>\n    \u003Cstrong>=\u003C/strong>\n    \u003Cspan id=\"functionOutput\">?\u003C/span>\n    \u003Cbr />\n    \u003Cbutton>Calculate!\u003C/button>\n\n    \u003Cscript>\n      fetch(\"./stack.json\").then(response => {\n        response.json().then(myJson => {\n          const functionUrl = myJson.ServiceEndpoint + \"/add\";\n          const inputA = document.querySelector(\"#inputA\");\n          const inputB = document.querySelector(\"#inputB\");\n          const output = document.querySelector(\"#functionOutput\");\n\n          document.querySelector(\"button\").addEventListener(\"click\", () => {\n            const A = Number(inputA.value);\n            const B = Number(inputB.value);\n\n            fetch(functionUrl + \"?A=\" + A + \"&B=\" + B)\n              .then(response => response.text())\n              .then(result => (output.textContent = result));\n          });\n        });\n      });\n    \u003C/script>\n  \u003C/body>\n\u003C/html>\n\n```\n\n\nLastly, open `serverless.yml` and add an \"add\" function entry below our\n\"hello\" function like so:\n\n\n```yml\n\nfunctions:\n  hello:\n    handler: src/handler.hello\n    events:\n      - http:\n          path: hello\n          method: get\n          cors: true\n  add:\n    handler: src/handler.add\n    events:\n      - http:\n          path: add\n          method: get\n          cors: true\n```\n\n\nStage and commit these changes directly to the `master` branch. This will\nhave triggered a new pipeline automatically. You can visit \"CI/CD ->\nPipelines\" and watch it run.\n\n\nOnce the deployment is complete, our project page should look like this:\n\n\n![Step 5\nResult](https://about.gitlab.com/images/blogimages/serverless-js-project-template/step-5.1.gif){:\n.shadow.medium.center}\n\n\nVoilà, we've just created our own serverless function and deployed it\nwithout a single terminal command. There's a lot more you can do from here,\nbut this should be a good place to get started. Happy coding!\n\n\n\u003C!-- Content ends here -->\n\n\nCover image by [Kaushik Panchal](https://unsplash.com/@kaushikpanchal) on\n[Unsplash](https://unsplash.com/)\n\n{: .note}\n","unfiltered",[23,24,25],"integrations","features","cloud native",{"slug":27,"featured":6,"template":28},"serverless-js-project-template","BlogPost","content:en-us:blog:serverless-js-project-template.yml","yaml","Serverless Js Project Template","content","en-us/blog/serverless-js-project-template.yml","en-us/blog/serverless-js-project-template","yml",{"_path":37,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"data":39,"_id":459,"_type":30,"title":460,"_source":32,"_file":461,"_stem":462,"_extension":35},"/shared/en-us/main-navigation","en-us",{"logo":40,"freeTrial":45,"sales":50,"login":55,"items":60,"search":390,"minimal":421,"duo":440,"pricingDeployment":449},{"config":41},{"href":42,"dataGaName":43,"dataGaLocation":44},"/","gitlab logo","header",{"text":46,"config":47},"Get free trial",{"href":48,"dataGaName":49,"dataGaLocation":44},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":51,"config":52},"Talk to sales",{"href":53,"dataGaName":54,"dataGaLocation":44},"/sales/","sales",{"text":56,"config":57},"Sign in",{"href":58,"dataGaName":59,"dataGaLocation":44},"https://gitlab.com/users/sign_in/","sign in",[61,105,202,207,311,371],{"text":62,"config":63,"cards":65,"footer":88},"Platform",{"dataNavLevelOne":64},"platform",[66,72,80],{"title":62,"description":67,"link":68},"The most comprehensive AI-powered DevSecOps Platform",{"text":69,"config":70},"Explore our Platform",{"href":71,"dataGaName":64,"dataGaLocation":44},"/platform/",{"title":73,"description":74,"link":75},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":76,"config":77},"Meet GitLab Duo",{"href":78,"dataGaName":79,"dataGaLocation":44},"/gitlab-duo/","gitlab duo ai",{"title":81,"description":82,"link":83},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":84,"config":85},"Learn more",{"href":86,"dataGaName":87,"dataGaLocation":44},"/why-gitlab/","why gitlab",{"title":89,"items":90},"Get started with",[91,96,101],{"text":92,"config":93},"Platform Engineering",{"href":94,"dataGaName":95,"dataGaLocation":44},"/solutions/platform-engineering/","platform engineering",{"text":97,"config":98},"Developer Experience",{"href":99,"dataGaName":100,"dataGaLocation":44},"/developer-experience/","Developer experience",{"text":102,"config":103},"MLOps",{"href":104,"dataGaName":102,"dataGaLocation":44},"/topics/devops/the-role-of-ai-in-devops/",{"text":106,"left":107,"config":108,"link":110,"lists":114,"footer":184},"Product",true,{"dataNavLevelOne":109},"solutions",{"text":111,"config":112},"View all Solutions",{"href":113,"dataGaName":109,"dataGaLocation":44},"/solutions/",[115,140,163],{"title":116,"description":117,"link":118,"items":123},"Automation","CI/CD and automation to accelerate deployment",{"config":119},{"icon":120,"href":121,"dataGaName":122,"dataGaLocation":44},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[124,128,132,136],{"text":125,"config":126},"CI/CD",{"href":127,"dataGaLocation":44,"dataGaName":125},"/solutions/continuous-integration/",{"text":129,"config":130},"AI-Assisted Development",{"href":78,"dataGaLocation":44,"dataGaName":131},"AI assisted development",{"text":133,"config":134},"Source Code Management",{"href":135,"dataGaLocation":44,"dataGaName":133},"/solutions/source-code-management/",{"text":137,"config":138},"Automated Software Delivery",{"href":121,"dataGaLocation":44,"dataGaName":139},"Automated software delivery",{"title":141,"description":142,"link":143,"items":148},"Security","Deliver code faster without compromising security",{"config":144},{"href":145,"dataGaName":146,"dataGaLocation":44,"icon":147},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[149,153,158],{"text":150,"config":151},"Application Security Testing",{"href":145,"dataGaName":152,"dataGaLocation":44},"Application security testing",{"text":154,"config":155},"Software Supply Chain Security",{"href":156,"dataGaLocation":44,"dataGaName":157},"/solutions/supply-chain/","Software supply chain security",{"text":159,"config":160},"Software Compliance",{"href":161,"dataGaName":162,"dataGaLocation":44},"/solutions/software-compliance/","software compliance",{"title":164,"link":165,"items":170},"Measurement",{"config":166},{"icon":167,"href":168,"dataGaName":169,"dataGaLocation":44},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[171,175,179],{"text":172,"config":173},"Visibility & Measurement",{"href":168,"dataGaLocation":44,"dataGaName":174},"Visibility and Measurement",{"text":176,"config":177},"Value Stream Management",{"href":178,"dataGaLocation":44,"dataGaName":176},"/solutions/value-stream-management/",{"text":180,"config":181},"Analytics & Insights",{"href":182,"dataGaLocation":44,"dataGaName":183},"/solutions/analytics-and-insights/","Analytics and insights",{"title":185,"items":186},"GitLab for",[187,192,197],{"text":188,"config":189},"Enterprise",{"href":190,"dataGaLocation":44,"dataGaName":191},"/enterprise/","enterprise",{"text":193,"config":194},"Small Business",{"href":195,"dataGaLocation":44,"dataGaName":196},"/small-business/","small business",{"text":198,"config":199},"Public Sector",{"href":200,"dataGaLocation":44,"dataGaName":201},"/solutions/public-sector/","public sector",{"text":203,"config":204},"Pricing",{"href":205,"dataGaName":206,"dataGaLocation":44,"dataNavLevelOne":206},"/pricing/","pricing",{"text":208,"config":209,"link":211,"lists":215,"feature":298},"Resources",{"dataNavLevelOne":210},"resources",{"text":212,"config":213},"View all resources",{"href":214,"dataGaName":210,"dataGaLocation":44},"/resources/",[216,248,270],{"title":217,"items":218},"Getting started",[219,224,229,234,239,244],{"text":220,"config":221},"Install",{"href":222,"dataGaName":223,"dataGaLocation":44},"/install/","install",{"text":225,"config":226},"Quick start guides",{"href":227,"dataGaName":228,"dataGaLocation":44},"/get-started/","quick setup checklists",{"text":230,"config":231},"Learn",{"href":232,"dataGaLocation":44,"dataGaName":233},"https://university.gitlab.com/","learn",{"text":235,"config":236},"Product documentation",{"href":237,"dataGaName":238,"dataGaLocation":44},"https://docs.gitlab.com/","product documentation",{"text":240,"config":241},"Best practice videos",{"href":242,"dataGaName":243,"dataGaLocation":44},"/getting-started-videos/","best practice videos",{"text":245,"config":246},"Integrations",{"href":247,"dataGaName":23,"dataGaLocation":44},"/integrations/",{"title":249,"items":250},"Discover",[251,256,260,265],{"text":252,"config":253},"Customer success stories",{"href":254,"dataGaName":255,"dataGaLocation":44},"/customers/","customer success stories",{"text":257,"config":258},"Blog",{"href":259,"dataGaName":5,"dataGaLocation":44},"/blog/",{"text":261,"config":262},"Remote",{"href":263,"dataGaName":264,"dataGaLocation":44},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":266,"config":267},"TeamOps",{"href":268,"dataGaName":269,"dataGaLocation":44},"/teamops/","teamops",{"title":271,"items":272},"Connect",[273,278,283,288,293],{"text":274,"config":275},"GitLab Services",{"href":276,"dataGaName":277,"dataGaLocation":44},"/services/","services",{"text":279,"config":280},"Community",{"href":281,"dataGaName":282,"dataGaLocation":44},"/community/","community",{"text":284,"config":285},"Forum",{"href":286,"dataGaName":287,"dataGaLocation":44},"https://forum.gitlab.com/","forum",{"text":289,"config":290},"Events",{"href":291,"dataGaName":292,"dataGaLocation":44},"/events/","events",{"text":294,"config":295},"Partners",{"href":296,"dataGaName":297,"dataGaLocation":44},"/partners/","partners",{"backgroundColor":299,"textColor":300,"text":301,"image":302,"link":306},"#2f2a6b","#fff","Insights for the future of software development",{"altText":303,"config":304},"the source promo card",{"src":305},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":307,"config":308},"Read the latest",{"href":309,"dataGaName":310,"dataGaLocation":44},"/the-source/","the source",{"text":312,"config":313,"lists":315},"Company",{"dataNavLevelOne":314},"company",[316],{"items":317},[318,323,329,331,336,341,346,351,356,361,366],{"text":319,"config":320},"About",{"href":321,"dataGaName":322,"dataGaLocation":44},"/company/","about",{"text":324,"config":325,"footerGa":328},"Jobs",{"href":326,"dataGaName":327,"dataGaLocation":44},"/jobs/","jobs",{"dataGaName":327},{"text":289,"config":330},{"href":291,"dataGaName":292,"dataGaLocation":44},{"text":332,"config":333},"Leadership",{"href":334,"dataGaName":335,"dataGaLocation":44},"/company/team/e-group/","leadership",{"text":337,"config":338},"Team",{"href":339,"dataGaName":340,"dataGaLocation":44},"/company/team/","team",{"text":342,"config":343},"Handbook",{"href":344,"dataGaName":345,"dataGaLocation":44},"https://handbook.gitlab.com/","handbook",{"text":347,"config":348},"Investor relations",{"href":349,"dataGaName":350,"dataGaLocation":44},"https://ir.gitlab.com/","investor relations",{"text":352,"config":353},"Trust Center",{"href":354,"dataGaName":355,"dataGaLocation":44},"/security/","trust center",{"text":357,"config":358},"AI Transparency Center",{"href":359,"dataGaName":360,"dataGaLocation":44},"/ai-transparency-center/","ai transparency center",{"text":362,"config":363},"Newsletter",{"href":364,"dataGaName":365,"dataGaLocation":44},"/company/contact/","newsletter",{"text":367,"config":368},"Press",{"href":369,"dataGaName":370,"dataGaLocation":44},"/press/","press",{"text":372,"config":373,"lists":374},"Contact us",{"dataNavLevelOne":314},[375],{"items":376},[377,380,385],{"text":51,"config":378},{"href":53,"dataGaName":379,"dataGaLocation":44},"talk to sales",{"text":381,"config":382},"Support portal",{"href":383,"dataGaName":384,"dataGaLocation":44},"https://support.gitlab.com","support portal",{"text":386,"config":387},"Customer portal",{"href":388,"dataGaName":389,"dataGaLocation":44},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":391,"login":392,"suggestions":399},"Close",{"text":393,"link":394},"To search repositories and projects, login to",{"text":395,"config":396},"gitlab.com",{"href":58,"dataGaName":397,"dataGaLocation":398},"search login","search",{"text":400,"default":401},"Suggestions",[402,404,408,410,414,418],{"text":73,"config":403},{"href":78,"dataGaName":73,"dataGaLocation":398},{"text":405,"config":406},"Code Suggestions (AI)",{"href":407,"dataGaName":405,"dataGaLocation":398},"/solutions/code-suggestions/",{"text":125,"config":409},{"href":127,"dataGaName":125,"dataGaLocation":398},{"text":411,"config":412},"GitLab on AWS",{"href":413,"dataGaName":411,"dataGaLocation":398},"/partners/technology-partners/aws/",{"text":415,"config":416},"GitLab on Google Cloud",{"href":417,"dataGaName":415,"dataGaLocation":398},"/partners/technology-partners/google-cloud-platform/",{"text":419,"config":420},"Why GitLab?",{"href":86,"dataGaName":419,"dataGaLocation":398},{"freeTrial":422,"mobileIcon":427,"desktopIcon":432,"secondaryButton":435},{"text":423,"config":424},"Start free trial",{"href":425,"dataGaName":49,"dataGaLocation":426},"https://gitlab.com/-/trials/new/","nav",{"altText":428,"config":429},"Gitlab Icon",{"src":430,"dataGaName":431,"dataGaLocation":426},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":428,"config":433},{"src":434,"dataGaName":431,"dataGaLocation":426},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":436,"config":437},"Get Started",{"href":438,"dataGaName":439,"dataGaLocation":426},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":441,"mobileIcon":445,"desktopIcon":447},{"text":442,"config":443},"Learn more about GitLab Duo",{"href":78,"dataGaName":444,"dataGaLocation":426},"gitlab duo",{"altText":428,"config":446},{"src":430,"dataGaName":431,"dataGaLocation":426},{"altText":428,"config":448},{"src":434,"dataGaName":431,"dataGaLocation":426},{"freeTrial":450,"mobileIcon":455,"desktopIcon":457},{"text":451,"config":452},"Back to pricing",{"href":205,"dataGaName":453,"dataGaLocation":426,"icon":454},"back to pricing","GoBack",{"altText":428,"config":456},{"src":430,"dataGaName":431,"dataGaLocation":426},{"altText":428,"config":458},{"src":434,"dataGaName":431,"dataGaLocation":426},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":464,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"title":465,"button":466,"image":471,"config":475,"_id":477,"_type":30,"_source":32,"_file":478,"_stem":479,"_extension":35},"/shared/en-us/banner","is now in public beta!",{"text":467,"config":468},"Try the Beta",{"href":469,"dataGaName":470,"dataGaLocation":44},"/gitlab-duo/agent-platform/","duo banner",{"altText":472,"config":473},"GitLab Duo Agent Platform",{"src":474},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":476},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":481,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"data":482,"_id":720,"_type":30,"title":721,"_source":32,"_file":722,"_stem":723,"_extension":35},"/shared/en-us/main-footer",{"text":483,"source":484,"edit":490,"contribute":495,"config":500,"items":505,"minimal":712},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":485,"config":486},"View page source",{"href":487,"dataGaName":488,"dataGaLocation":489},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":491,"config":492},"Edit this page",{"href":493,"dataGaName":494,"dataGaLocation":489},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":496,"config":497},"Please contribute",{"href":498,"dataGaName":499,"dataGaLocation":489},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":501,"facebook":502,"youtube":503,"linkedin":504},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[506,553,605,649,678],{"title":203,"links":507,"subMenu":522},[508,512,517],{"text":509,"config":510},"View plans",{"href":205,"dataGaName":511,"dataGaLocation":489},"view plans",{"text":513,"config":514},"Why Premium?",{"href":515,"dataGaName":516,"dataGaLocation":489},"/pricing/premium/","why premium",{"text":518,"config":519},"Why Ultimate?",{"href":520,"dataGaName":521,"dataGaLocation":489},"/pricing/ultimate/","why ultimate",[523],{"title":524,"links":525},"Contact Us",[526,529,531,533,538,543,548],{"text":527,"config":528},"Contact sales",{"href":53,"dataGaName":54,"dataGaLocation":489},{"text":381,"config":530},{"href":383,"dataGaName":384,"dataGaLocation":489},{"text":386,"config":532},{"href":388,"dataGaName":389,"dataGaLocation":489},{"text":534,"config":535},"Status",{"href":536,"dataGaName":537,"dataGaLocation":489},"https://status.gitlab.com/","status",{"text":539,"config":540},"Terms of use",{"href":541,"dataGaName":542,"dataGaLocation":489},"/terms/","terms of use",{"text":544,"config":545},"Privacy statement",{"href":546,"dataGaName":547,"dataGaLocation":489},"/privacy/","privacy statement",{"text":549,"config":550},"Cookie preferences",{"dataGaName":551,"dataGaLocation":489,"id":552,"isOneTrustButton":107},"cookie preferences","ot-sdk-btn",{"title":106,"links":554,"subMenu":562},[555,559],{"text":556,"config":557},"DevSecOps platform",{"href":71,"dataGaName":558,"dataGaLocation":489},"devsecops platform",{"text":129,"config":560},{"href":78,"dataGaName":561,"dataGaLocation":489},"ai-assisted development",[563],{"title":564,"links":565},"Topics",[566,571,576,581,586,591,595,600],{"text":567,"config":568},"CICD",{"href":569,"dataGaName":570,"dataGaLocation":489},"/topics/ci-cd/","cicd",{"text":572,"config":573},"GitOps",{"href":574,"dataGaName":575,"dataGaLocation":489},"/topics/gitops/","gitops",{"text":577,"config":578},"DevOps",{"href":579,"dataGaName":580,"dataGaLocation":489},"/topics/devops/","devops",{"text":582,"config":583},"Version Control",{"href":584,"dataGaName":585,"dataGaLocation":489},"/topics/version-control/","version control",{"text":587,"config":588},"DevSecOps",{"href":589,"dataGaName":590,"dataGaLocation":489},"/topics/devsecops/","devsecops",{"text":592,"config":593},"Cloud Native",{"href":594,"dataGaName":25,"dataGaLocation":489},"/topics/cloud-native/",{"text":596,"config":597},"AI for Coding",{"href":598,"dataGaName":599,"dataGaLocation":489},"/topics/devops/ai-for-coding/","ai for coding",{"text":601,"config":602},"Agentic AI",{"href":603,"dataGaName":604,"dataGaLocation":489},"/topics/agentic-ai/","agentic ai",{"title":606,"links":607},"Solutions",[608,610,612,617,621,624,628,631,633,636,639,644],{"text":150,"config":609},{"href":145,"dataGaName":150,"dataGaLocation":489},{"text":139,"config":611},{"href":121,"dataGaName":122,"dataGaLocation":489},{"text":613,"config":614},"Agile development",{"href":615,"dataGaName":616,"dataGaLocation":489},"/solutions/agile-delivery/","agile delivery",{"text":618,"config":619},"SCM",{"href":135,"dataGaName":620,"dataGaLocation":489},"source code management",{"text":567,"config":622},{"href":127,"dataGaName":623,"dataGaLocation":489},"continuous integration & delivery",{"text":625,"config":626},"Value stream management",{"href":178,"dataGaName":627,"dataGaLocation":489},"value stream management",{"text":572,"config":629},{"href":630,"dataGaName":575,"dataGaLocation":489},"/solutions/gitops/",{"text":188,"config":632},{"href":190,"dataGaName":191,"dataGaLocation":489},{"text":634,"config":635},"Small business",{"href":195,"dataGaName":196,"dataGaLocation":489},{"text":637,"config":638},"Public sector",{"href":200,"dataGaName":201,"dataGaLocation":489},{"text":640,"config":641},"Education",{"href":642,"dataGaName":643,"dataGaLocation":489},"/solutions/education/","education",{"text":645,"config":646},"Financial services",{"href":647,"dataGaName":648,"dataGaLocation":489},"/solutions/finance/","financial services",{"title":208,"links":650},[651,653,655,657,660,662,664,666,668,670,672,674,676],{"text":220,"config":652},{"href":222,"dataGaName":223,"dataGaLocation":489},{"text":225,"config":654},{"href":227,"dataGaName":228,"dataGaLocation":489},{"text":230,"config":656},{"href":232,"dataGaName":233,"dataGaLocation":489},{"text":235,"config":658},{"href":237,"dataGaName":659,"dataGaLocation":489},"docs",{"text":257,"config":661},{"href":259,"dataGaName":5,"dataGaLocation":489},{"text":252,"config":663},{"href":254,"dataGaName":255,"dataGaLocation":489},{"text":261,"config":665},{"href":263,"dataGaName":264,"dataGaLocation":489},{"text":274,"config":667},{"href":276,"dataGaName":277,"dataGaLocation":489},{"text":266,"config":669},{"href":268,"dataGaName":269,"dataGaLocation":489},{"text":279,"config":671},{"href":281,"dataGaName":282,"dataGaLocation":489},{"text":284,"config":673},{"href":286,"dataGaName":287,"dataGaLocation":489},{"text":289,"config":675},{"href":291,"dataGaName":292,"dataGaLocation":489},{"text":294,"config":677},{"href":296,"dataGaName":297,"dataGaLocation":489},{"title":312,"links":679},[680,682,684,686,688,690,692,696,701,703,705,707],{"text":319,"config":681},{"href":321,"dataGaName":314,"dataGaLocation":489},{"text":324,"config":683},{"href":326,"dataGaName":327,"dataGaLocation":489},{"text":332,"config":685},{"href":334,"dataGaName":335,"dataGaLocation":489},{"text":337,"config":687},{"href":339,"dataGaName":340,"dataGaLocation":489},{"text":342,"config":689},{"href":344,"dataGaName":345,"dataGaLocation":489},{"text":347,"config":691},{"href":349,"dataGaName":350,"dataGaLocation":489},{"text":693,"config":694},"Sustainability",{"href":695,"dataGaName":693,"dataGaLocation":489},"/sustainability/",{"text":697,"config":698},"Diversity, inclusion and belonging (DIB)",{"href":699,"dataGaName":700,"dataGaLocation":489},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":352,"config":702},{"href":354,"dataGaName":355,"dataGaLocation":489},{"text":362,"config":704},{"href":364,"dataGaName":365,"dataGaLocation":489},{"text":367,"config":706},{"href":369,"dataGaName":370,"dataGaLocation":489},{"text":708,"config":709},"Modern Slavery Transparency Statement",{"href":710,"dataGaName":711,"dataGaLocation":489},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":713},[714,716,718],{"text":539,"config":715},{"href":541,"dataGaName":542,"dataGaLocation":489},{"text":544,"config":717},{"href":546,"dataGaName":547,"dataGaLocation":489},{"text":549,"config":719},{"dataGaName":551,"dataGaLocation":489,"id":552,"isOneTrustButton":107},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[725],{"_path":726,"_dir":727,"_draft":6,"_partial":6,"_locale":7,"content":728,"config":731,"_id":733,"_type":30,"title":18,"_source":32,"_file":734,"_stem":735,"_extension":35},"/en-us/blog/authors/mike-greiling","authors",{"name":18,"config":729},{"headshot":7,"ctfId":730},"mikegreiling",{"template":732},"BlogAuthor","content:en-us:blog:authors:mike-greiling.yml","en-us/blog/authors/mike-greiling.yml","en-us/blog/authors/mike-greiling",{"_path":737,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"header":738,"eyebrow":739,"blurb":740,"button":741,"secondaryButton":745,"_id":747,"_type":30,"title":748,"_source":32,"_file":749,"_stem":750,"_extension":35},"/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":46,"config":742},{"href":743,"dataGaName":49,"dataGaLocation":744},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":51,"config":746},{"href":53,"dataGaName":54,"dataGaLocation":744},"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":752,"content":753,"config":756,"_id":29,"_type":30,"title":31,"_source":32,"_file":33,"_stem":34,"_extension":35},{"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":754,"heroImage":11,"date":19,"body":20,"category":21,"tags":755},[18],[23,24,25],{"slug":27,"featured":6,"template":28},1761814437552]