[{"data":1,"prerenderedAt":2650},["ShallowReactive",2],{"navigation_docs":3,"-migration-guides-firebase-remote-config":271,"-migration-guides-firebase-remote-config-surround":2647},[4,10,57,83,236,256],{"title":5,"path":6,"stem":7,"icon":8,"exact":9},"Introduction","\u002F","0.index","i-lucide-book-open",true,{"title":11,"icon":12,"modifiedAt":13,"path":14,"stem":15,"children":16,"page":12},"Getting Started",false,"2026-04-30T19:15:33.000Z","\u002Fgetting-started","1.getting-started",[17,22,27,32,37,42,47,52],{"title":18,"path":19,"stem":20,"icon":21},"Quickstart","\u002Fgetting-started\u002Fquickstart","1.getting-started\u002F1.quickstart","i-lucide-fast-forward",{"title":23,"path":24,"stem":25,"icon":26},"Core Concepts","\u002Fgetting-started\u002Fcore-concepts","1.getting-started\u002F2.core-concepts","i-lucide-workflow",{"title":28,"path":29,"stem":30,"icon":31},"Configs Anatomy","\u002Fgetting-started\u002Fconfigs","1.getting-started\u002F3.configs","i-lucide-file-cog",{"title":33,"path":34,"stem":35,"icon":36},"Architecture","\u002Fgetting-started\u002Farchitecture","1.getting-started\u002F4.architecture","i-lucide-layers",{"title":38,"path":39,"stem":40,"icon":41},"JSON Schema Validation","\u002Fgetting-started\u002Fjson-schema-validation","1.getting-started\u002F5.json-schema-validation","i-lucide-braces",{"title":43,"path":44,"stem":45,"icon":46},"Testing Rules","\u002Fgetting-started\u002Ftesting-targeting-rules","1.getting-started\u002F6.testing-targeting-rules","i-lucide-flask-conical",{"title":48,"path":49,"stem":50,"icon":51},"Segments","\u002Fgetting-started\u002Fsegments","1.getting-started\u002F7.segments","i-lucide-squares-intersect",{"title":53,"path":54,"stem":55,"icon":56},"Pricing & Billing","\u002Fgetting-started\u002Fpricing-and-billing","1.getting-started\u002F8.pricing-and-billing","i-lucide-credit-card",{"title":58,"modifiedAt":59,"defaultOpen":9,"path":60,"stem":61,"children":62,"page":12},"Monitoring","2026-09-24T23:33:20.000Z","\u002Fmonitoring","2.monitoring",[63,68,73,78],{"title":64,"path":65,"stem":66,"icon":67},"Activity","\u002Fmonitoring\u002Factivity","2.monitoring\u002F1.activity","i-lucide-activity",{"title":69,"path":70,"stem":71,"icon":72},"Lifecycle","\u002Fmonitoring\u002Flifecycle","2.monitoring\u002F2.lifecycle","i-lucide-recycle",{"title":74,"path":75,"stem":76,"icon":77},"Alerts","\u002Fmonitoring\u002Falerts","2.monitoring\u002F3.alerts","i-lucide-bell",{"title":79,"path":80,"stem":81,"icon":82},"Dynamic Detection","\u002Fmonitoring\u002Fdynamic-detection","2.monitoring\u002F4.dynamic-detection","i-lucide-hat-glasses",{"title":84,"modifiedAt":59,"defaultOpen":9,"path":85,"stem":86,"children":87,"page":12},"SDKs","\u002Fsdks","3.sdks",[88,93,114,139,155,186,231],{"title":89,"path":90,"stem":91,"icon":92},"Available SDKs","\u002Fsdks\u002Favailable-sdks","3.sdks\u002F1.available-sdks","i-lucide-list",{"title":94,"modifiedAt":59,"icon":95,"defaultOpen":12,"path":96,"stem":97,"children":98,"page":12},"Browser SDKs","i-lucide-monitor","\u002Fsdks\u002Fbrowser","3.sdks\u002F2.browser",[99,104,109],{"title":100,"path":101,"stem":102,"icon":103},"Javascript","\u002Fsdks\u002Fbrowser\u002Fjavascript","3.sdks\u002F2.browser\u002F1.javascript","cd-logos-javascript",{"title":105,"path":106,"stem":107,"icon":108},"React","\u002Fsdks\u002Fbrowser\u002Freact","3.sdks\u002F2.browser\u002F2.react","cd-logos-react-light",{"title":110,"path":111,"stem":112,"icon":113},"Vue","\u002Fsdks\u002Fbrowser\u002Fvue","3.sdks\u002F2.browser\u002F3.vue","cd-logos-vue",{"title":115,"modifiedAt":59,"icon":116,"defaultOpen":12,"path":117,"stem":118,"children":119,"page":12},"Mobile SDKs","i-lucide-smartphone","\u002Fsdks\u002Fmobile","3.sdks\u002F3.mobile",[120,124,129,134],{"title":121,"path":122,"stem":123,"icon":108},"React Native","\u002Fsdks\u002Fmobile\u002Freact-native","3.sdks\u002F3.mobile\u002F1.react-native",{"title":125,"path":126,"stem":127,"icon":128},"Flutter","\u002Fsdks\u002Fmobile\u002Fflutter","3.sdks\u002F3.mobile\u002F2.flutter","cd-logos-flutter",{"title":130,"path":131,"stem":132,"icon":133},"Swift","\u002Fsdks\u002Fmobile\u002Fswift","3.sdks\u002F3.mobile\u002F3.swift","cd-logos-swift",{"title":135,"path":136,"stem":137,"icon":138},"Android","\u002Fsdks\u002Fmobile\u002Fandroid","3.sdks\u002F3.mobile\u002F4.android","cd-logos-android",{"title":140,"modifiedAt":59,"icon":141,"defaultOpen":12,"path":142,"stem":143,"children":144,"page":12},"Meta-framework SDKs","i-lucide-monitor-smartphone","\u002Fsdks\u002Fmeta","3.sdks\u002F4.meta",[145,150],{"title":146,"path":147,"stem":148,"icon":149},"Next.js","\u002Fsdks\u002Fmeta\u002Fnextjs","3.sdks\u002F4.meta\u002F1.nextjs","cd-logos-nextjs",{"title":151,"path":152,"stem":153,"icon":154},"Nuxt","\u002Fsdks\u002Fmeta\u002Fnuxt","3.sdks\u002F4.meta\u002F2.nuxt","cd-logos-nuxt",{"title":156,"modifiedAt":59,"icon":157,"defaultOpen":12,"path":158,"stem":159,"children":160,"page":12},"Server SDKs","i-lucide-server","\u002Fsdks\u002Fserver","3.sdks\u002F5.server",[161,166,171,176,181],{"title":162,"path":163,"stem":164,"icon":165},"Node.js","\u002Fsdks\u002Fserver\u002Fnode-js","3.sdks\u002F5.server\u002F1.node-js","cd-logos-nodejs",{"title":167,"path":168,"stem":169,"icon":170},"Python","\u002Fsdks\u002Fserver\u002Fpython","3.sdks\u002F5.server\u002F2.python","cd-logos-python",{"title":172,"path":173,"stem":174,"icon":175},"Java","\u002Fsdks\u002Fserver\u002Fjava","3.sdks\u002F5.server\u002F3.java","cd-logos-java",{"title":177,"path":178,"stem":179,"icon":180},".NET","\u002Fsdks\u002Fserver\u002Fdotnet","3.sdks\u002F5.server\u002F4.dotnet","cd-logos-dotnet",{"title":182,"path":183,"stem":184,"icon":185},"Go","\u002Fsdks\u002Fserver\u002Fgo","3.sdks\u002F5.server\u002F5.go","cd-logos-go",{"title":187,"modifiedAt":59,"icon":188,"defaultOpen":12,"path":189,"stem":190,"children":191},"OpenFeature Providers","cd-logos-openfeature","\u002Fsdks\u002Fopenfeature","3.sdks\u002F6.openfeature\u002Findex",[192,194,199,203,207,211,215,219,223,227],{"title":193,"path":189,"stem":190,"icon":188},"Overview",{"title":195,"path":196,"stem":197,"icon":188,"icons":198},"Web","\u002Fsdks\u002Fopenfeature\u002Fweb","3.sdks\u002F6.openfeature\u002F1.web",[188,103],{"title":130,"path":200,"stem":201,"icon":188,"icons":202},"\u002Fsdks\u002Fopenfeature\u002Fswift","3.sdks\u002F6.openfeature\u002F2.swift",[188,133],{"title":135,"path":204,"stem":205,"icon":188,"icons":206},"\u002Fsdks\u002Fopenfeature\u002Fandroid","3.sdks\u002F6.openfeature\u002F3.android",[188,138],{"title":125,"path":208,"stem":209,"icon":188,"icons":210},"\u002Fsdks\u002Fopenfeature\u002Fflutter","3.sdks\u002F6.openfeature\u002F4.flutter",[188,128],{"title":162,"path":212,"stem":213,"icon":188,"icons":214},"\u002Fsdks\u002Fopenfeature\u002Fnode-js","3.sdks\u002F6.openfeature\u002F5.node-js",[188,165],{"title":167,"path":216,"stem":217,"icon":188,"icons":218},"\u002Fsdks\u002Fopenfeature\u002Fpython","3.sdks\u002F6.openfeature\u002F6.python",[188,170],{"title":172,"path":220,"stem":221,"icon":188,"icons":222},"\u002Fsdks\u002Fopenfeature\u002Fjava","3.sdks\u002F6.openfeature\u002F7.java",[188,175],{"title":177,"path":224,"stem":225,"icon":188,"icons":226},"\u002Fsdks\u002Fopenfeature\u002Fdotnet","3.sdks\u002F6.openfeature\u002F8.dotnet",[188,180],{"title":182,"path":228,"stem":229,"icon":188,"icons":230},"\u002Fsdks\u002Fopenfeature\u002Fgo","3.sdks\u002F6.openfeature\u002F9.go",[188,185],{"title":232,"path":233,"stem":234,"icon":235},"Maven Repository","\u002Fsdks\u002Fmaven-repository","3.sdks\u002F7.maven-repository","i-lucide-package",{"title":237,"modifiedAt":59,"defaultOpen":9,"path":238,"stem":239,"children":240,"page":12},"Integrations","\u002Fintegrations","4.integrations",[241,246,251],{"title":242,"path":243,"stem":244,"icon":245},"Terraform","\u002Fintegrations\u002Fterraform","4.integrations\u002F1.terraform","cd-logos-terraform",{"title":247,"path":248,"stem":249,"icon":250},"MCP","\u002Fintegrations\u002Fmcp","4.integrations\u002F2.mcp","cd-logos-mcp",{"title":252,"path":253,"stem":254,"icon":255},"Admin API","\u002Fintegrations\u002Fadmin-api","4.integrations\u002F3.admin-api","i-lucide-blocks",{"title":257,"modifiedAt":258,"defaultOpen":9,"path":259,"stem":260,"children":261,"page":12},"Migration Guides","2026-10-16T17:57:49.000Z","\u002Fmigration-guides","5.migration-guides",[262,267],{"title":263,"path":264,"stem":265,"icon":266},"From LaunchDarkly","\u002Fmigration-guides\u002Flaunchdarkly","5.migration-guides\u002F1.launchdarkly","i-lucide-baggage-claim",{"title":268,"path":269,"stem":270,"icon":266},"From Firebase Remote Config","\u002Fmigration-guides\u002Ffirebase-remote-config","5.migration-guides\u002F2.firebase-remote-config",{"id":272,"title":273,"body":274,"description":2638,"extension":2639,"links":2640,"meta":2641,"navigation":2642,"path":269,"seo":2643,"stem":270,"__hash__":2646},"docs\u002F5.migration-guides\u002F2.firebase-remote-config.md","Migrating from Firebase Remote Config",{"type":275,"value":276,"toc":2620},"minimark",[277,281,288,293,351,355,360,584,588,595,724,727,731,775,779,899,903,907,910,913,941,944,980,984,988,991,995,1005,1308,1313,1317,1320,1645,1652,1656,1666,1907,1925,1929,1935,2473,2476,2480,2575,2582,2586,2589,2609,2616],[278,279,280],"p",{},"This guide is for apps that read their remote configuration from Firebase Remote Config and want to move it to ConfigDirector. It maps the Remote Config concepts onto ConfigDirector's, walks through recreating the parameters as configs, and shows how to switch each SDK over so that both services run side by side until you remove Remote Config.",[278,282,283,284,287],{},"If you are new to ConfigDirector, read ",[285,286,23],"a",{"href":24}," first. It takes a few minutes and makes the mapping below easier to follow.",[289,290,292],"h2",{"id":291},"before-you-start","Before you start",[294,295,296,317,323],"ol",{},[297,298,299,303,304,308,309,316],"li",{},[300,301,302],"strong",{},"Export the Remote Config template."," The Firebase console, the Firebase CLI (",[305,306,307],"code",{},"firebase remoteconfig:get -o remoteconfig.template.json","), and the REST API all export the template as JSON, with every parameter, its default and conditional values, its value type, and the project's conditions. That file is the list you work from. See ",[285,310,315],{"href":311,"rel":312,"target":314},"https:\u002F\u002Ffirebase.google.com\u002Fdocs\u002Fremote-config\u002Ftemplates",[313],"noopener","_blank","Firebase's template documentation",".",[297,318,319,322],{},[300,320,321],{},"Decide which parameters not to move."," A migration is the best moment to clean up. A parameter that has had the same value everywhere since it was added, or that no shipped version of the app still reads, has nothing left to decide. Hardcode that value instead of recreating the parameter.",[297,324,325,328,329,335,336,339,340,343,344,339,347,350],{},[300,326,327],{},"Create your ConfigDirector organization and project."," ",[285,330,334],{"href":331,"target":314,"rel":332},"https:\u002F\u002Fapp.configdirector.com\u002F",[313,333],"noreferrer","Sign up"," and create one project for the app. If you kept one Firebase project per stage, such as ",[305,337,338],{},"my-app-dev"," and ",[305,341,342],{},"my-app-prod",", they become environments of this one project: ",[305,345,346],{},"Test",[305,348,349],{},"Production"," are created for you, and you can add more. Mark the environments that serve real traffic as live.",[289,352,354],{"id":353},"how-the-concepts-map","How the concepts map",[356,357,359],"h3",{"id":358},"parameters-and-values","Parameters and values",[361,362,363,376],"table",{},[364,365,366],"thead",{},[367,368,369,373],"tr",{},[370,371,372],"th",{},"Firebase Remote Config",[370,374,375],{},"ConfigDirector",[377,378,379,398,419,468,480,492,504,512,519,535,549,557,572],"tbody",{},[367,380,381,385],{},[382,383,384],"td",{},"Firebase project, one per stage",[382,386,387,388,392,393,397],{},"One ",[285,389,391],{"href":390},"\u002Fgetting-started\u002Fcore-concepts#projects","project"," with an ",[285,394,396],{"href":395},"\u002Fgetting-started\u002Fcore-concepts#environments","environment"," per stage. Each environment has its own SDK keys and its own targeting rules for every config.",[367,399,400,403],{},[382,401,402],{},"Parameter",[382,404,405,408,409,412,413,416,417,316],{},[285,406,407],{"href":29},"Config",". A boolean parameter that gates a feature is a config with the ",[305,410,411],{},"Feature flag"," role if it is temporary, or ",[305,414,415],{},"Kill switch"," if it stays; everything else is a ",[305,418,407],{},[367,420,421,424],{},[382,422,423],{},"Value type: string, boolean, number, JSON",[382,425,426,427,430,431,434,435,434,438,441,442,434,445,448,449,434,452,455,456,459,460,462,463,465,466,316],{},"Config ",[300,428,429],{},"type",": ",[305,432,433],{},"String",", ",[305,436,437],{},"Boolean",[305,439,440],{},"Integer"," or ",[305,443,444],{},"Float",[305,446,447],{},"JSON",". ConfigDirector also has ",[305,450,451],{},"Enum",[305,453,454],{},"URL",", and ",[305,457,458],{},"Timespan",", which validate the value as that type. A string parameter with a fixed set of values is an ",[305,461,451],{},"; a string holding a URL is a ",[305,464,454],{},"; a number of milliseconds or seconds is a ",[305,467,458],{},[367,469,470,473],{},[382,471,472],{},"Default value",[382,474,475,476,479],{},"The ",[300,477,478],{},"default targeting rule value",": the value of the last rule in each environment, served when no other rule matches.",[367,481,482,485],{},[382,483,484],{},"Conditional value",[382,486,487,488,491],{},"A ",[300,489,490],{},"conditional rule"," above the default targeting rule, with the condition and the value it serves. Rules are checked in order; the first that matches serves its value.",[367,493,494,497],{},[382,495,496],{},"Condition, named and shared across parameters",[382,498,499,500,503],{},"Conditions are written on each rule. A condition you reuse across many configs becomes a ",[285,501,502],{"href":49},"segment",", defined once per project and used by a rule as \"the context is in the segment\".",[367,505,506,509],{},[382,507,508],{},"Parameter group",[382,510,511],{},"Tags",[367,513,514,517],{},[382,515,516],{},"Description",[382,518,516],{},[367,520,521,524],{},[382,522,523],{},"Parameter key",[382,525,426,526,529,530,534],{},[300,527,528],{},"key",". Firebase keys made of letters, digits, and underscores are valid ConfigDirector keys, so keep them: the code change is then only the SDK call. A key can be ",[285,531,533],{"href":532},"\u002Fgetting-started\u002Fconfigs#key","renamed safely"," later, even in production.",[367,536,537,543],{},[382,538,539,540],{},"In-app default values, from XML, plist, JSON, or ",[305,541,542],{},"defaultConfig",[382,544,475,545,548],{},[300,546,547],{},"in-code default value",", passed with every read. It is returned when the client has not received values yet, and when the config is missing or has the wrong type.",[367,550,551,554],{},[382,552,553],{},"Template versions, diff, and rollback",[382,555,556],{},"The config's audit log, with who changed what, from where, and the before and after values. There is no one-click rollback: restore a value by setting it again.",[367,558,559,562],{},[382,560,561],{},"Template JSON, exported and published through the CLI or REST",[382,563,475,564,567,568,571],{},[285,565,566],{"href":243},"Terraform provider",", the ",[285,569,570],{"href":248},"MCP server",", and the Admin API. Configs and targeting rules are managed as code with the same validations as the dashboard.",[367,573,574,577],{},[382,575,576],{},"Value limits: 3,000 parameters, 1,000,000 characters",[382,578,579,580,316],{},"100 configs on Free, unlimited on Pay as you go. 16 KB per value and 1 MB per project. See ",[285,581,583],{"href":582},"\u002Fgetting-started\u002Fpricing-and-billing#limits","Pricing and billing",[356,585,587],{"id":586},"conditions","Conditions",[278,589,590,591,594],{},"Remote Config evaluates values per app instance, from signals it collects itself. ConfigDirector evaluates values per ",[300,592,593],{},"context",": the user, device, or other entity your app says it is evaluating for, with the traits your app gives it. Most Remote Config conditions become a condition on a trait that your app sets.",[361,596,597,606],{},[364,598,599],{},[367,600,601,604],{},[370,602,603],{},"Remote Config condition",[370,605,375],{},[377,607,608,624,645,667,678,690,702,710],{},[367,609,610,613],{},[382,611,612],{},"App version, build number",[382,614,615,616,619,620,623],{},"An ",[305,617,618],{},"appVersion"," condition, compared as a semantic version. The mobile SDKs read the app version from the platform when you do not set it; the browser SDK takes it from the ",[305,621,622],{},"metadata"," option.",[367,625,626,629],{},[382,627,628],{},"App, platform",[382,630,615,631,634,635,637,638,339,641,644],{},[305,632,633],{},"appName"," condition. Give each platform build its own name through the ",[305,636,622],{}," option, such as ",[305,639,640],{},"my-app-ios",[305,642,643],{},"my-app-android",", or use one config per platform.",[367,646,647,650],{},[382,648,649],{},"Country or region, language, device category, OS",[382,651,652,653,434,656,659,660,663,664,316],{},"A condition on a trait your app sets, such as ",[305,654,655],{},"\u002Fcountry",[305,657,658],{},"\u002Flanguage",", or ",[305,661,662],{},"\u002Fplatform",". ConfigDirector does not collect these on its own; put the ones your rules use into the context's ",[305,665,666],{},"traits",[367,668,669,672],{},[382,670,671],{},"User property, Analytics audience, custom signal",[382,673,674,675,677],{},"A condition on a trait, or a ",[285,676,502],{"href":49}," with the audience's definition. Traits can hold strings, numbers, booleans, arrays, and nested objects, and a condition reads a trait as text, a number, a semantic version, a datetime, an array, or a boolean.",[367,679,680,683],{},[382,681,682],{},"User in random percentile",[382,684,487,685,689],{},[285,686,688],{"href":687},"\u002Fgetting-started\u002Fcore-concepts#targeting-rules","percentage rollout",". Each context is assigned by its context kind and identifier, so a user keeps the same value on every device they sign in on, and across app restarts.",[367,691,692,695],{},[382,693,694],{},"First open time",[382,696,697,698,701],{},"A trait your app sets, such as ",[305,699,700],{},"\u002FfirstOpenedAt",", compared as a datetime.",[367,703,704,707],{},[382,705,706],{},"Date and time",[382,708,709],{},"Not available. There are no scheduled changes; change the rule when the time comes, or apply the change from a scheduled job through the Admin API, the Terraform provider, or the MCP server.",[367,711,712,715],{},[382,713,714],{},"Imported segment",[382,716,487,717,719,720,723],{},[285,718,502],{"href":49}," with the same definition, or a condition group with ",[305,721,722],{},"identifier is one of"," the listed identifiers.",[278,725,726],{},"Remote Config combines the clauses of a condition with AND, and so does a ConfigDirector rule: every condition of a rule must match. Where Remote Config applies the first matching conditional value in the order the conditions are listed, ConfigDirector applies the first matching rule.",[356,728,730],{"id":729},"experiments-and-rollouts","Experiments and rollouts",[361,732,733,742],{},[364,734,735],{},[367,736,737,740],{},[370,738,739],{},"Firebase",[370,741,375],{},[377,743,744,764],{},[367,745,746,749],{},[382,747,748],{},"A\u002FB Testing experiment on a parameter",[382,750,751,752,755,756,759,760,763],{},"A config with the ",[305,753,754],{},"Experiment"," role. It defines named ",[300,757,758],{},"variations"," and serves them to segments or by percentage. ConfigDirector does not measure the outcome: send the variation to your analytics, using the ",[305,761,762],{},"valueId"," every evaluation carries if you prefer not to send the value itself.",[367,765,766,769],{},[382,767,768],{},"Rollout with Crashlytics and Analytics metrics",[382,770,771,772,774],{},"A percentage rollout that you widen as you watch your own monitoring. ",[285,773,74],{"href":75}," tell you about problems with the config itself, such as a type mismatch or the in-code default value being served too often.",[356,776,778],{"id":777},"fetching-values","Fetching values",[361,780,781,789],{},[364,782,783],{},[367,784,785,787],{},[370,786,372],{},[370,788,375],{},[377,790,791,805,815,826,837,861,878,889],{},[367,792,793,796],{},[382,794,795],{},"Fetch, then activate",[382,797,798,801,802,804],{},[305,799,800],{},"initialize"," once, when the app starts. There is no activate step: values are ready to read as soon as ",[305,803,800],{}," completes.",[367,806,807,810],{},[382,808,809],{},"Minimum fetch interval, 12 hours by default",[382,811,812,813,316],{},"None. The SDK keeps a streaming connection open and receives every change within about a second of it being saved. Polling is available for environments where a persistent connection does not work. See ",[285,814,33],{"href":34},[367,816,817,820],{},[382,818,819],{},"Real-time config update listener, then activate",[382,821,822,825],{},[305,823,824],{},"watch"," a config, or subscribe to the stream or flow for its key. It emits the current value and then every change. Nothing has to be activated.",[367,827,828,831],{},[382,829,830],{},"Values persist on the device across restarts",[382,832,833,834,836],{},"Client SDKs hold values in memory. After a start, reads return the in-code default value until the first values arrive, which is usually well under a second. ",[305,835,800],{}," waits for them for up to its timeout, 3 seconds by default, and the client keeps connecting in the background after a timeout.",[367,838,839,842],{},[382,840,841],{},"Value source: static, default, remote",[382,843,475,844,430,847,850,851,434,854,659,857,860],{},[300,845,846],{},"evaluation reason",[305,848,849],{},"found-match"," when a value from ConfigDirector was served, or a reason such as ",[305,852,853],{},"client-not-ready",[305,855,856],{},"config-state-missing",[305,858,859],{},"type-mismatch"," when the in-code default value was. Every SDK exposes it, through a hook or an evaluation method.",[367,862,863,866],{},[382,864,865],{},"Firebase installation as the evaluated entity",[382,867,475,868,870,871,874,875,316],{},[300,869,593],{},": give it the user's identifier when they sign in, or leave the identifier out for an anonymous context, for which ConfigDirector derives a stable identifier from the SDK instance. A context of another kind, such as a ",[305,872,873],{},"device",", sets ",[305,876,877],{},"kind",[367,879,880,883],{},[382,881,882],{},"Server-side Remote Config, in the Admin SDK",[382,884,475,885,888],{},[285,886,887],{"href":90},"server SDKs",", with a server SDK key. They receive the targeting rules and evaluate every context locally.",[367,890,891,894],{},[382,892,893],{},"Pricing: 100,000 fetches a day free, then per fetch",[382,895,896,897,316],{},"A free allowance of 40,000 client sessions a month, then per session. A session is one client SDK instance for as long as it is used, however many values it reads or updates it receives. See ",[285,898,583],{"href":54},[900,901,902],"warning",{},"Do not move secrets. Remote Config documents that its values are not for sensitive data, and the same is true of ConfigDirector: values are delivered to the app and are not protected like a secrets vault.",[289,904,906],{"id":905},"recreate-the-parameters","Recreate the parameters",[278,908,909],{},"Create the configs in ConfigDirector while Remote Config keeps serving your app. Nothing changes for your users until the SDKs switch over.",[278,911,912],{},"For each parameter in the exported template:",[294,914,915,926,934],{},[297,916,917,918,921,922,925],{},"Create a config with the same key, the role and type from the tables above, and a lifetime: ",[305,919,920],{},"Temporary"," for a parameter you plan to remove once a feature is fully released, ",[305,923,924],{},"Permanent"," for one that stays. Set its initial value to the parameter's default value.",[297,927,928,929,455,931,933],{},"In each environment, recreate the conditional values as conditional rules, in the same order, with the parameter's default value as the default targeting rule value. A Firebase project per stage maps onto one environment each; a single Firebase project maps onto ",[305,930,349],{},[305,932,346],{}," gets the values you want while developing.",[297,935,936,937,940],{},"Check a few contexts with the ",[285,938,939],{"href":44},"targeting rules tester",". The result should be the value Remote Config serves them.",[278,942,943],{},"There are three ways to do this:",[945,946,947,953,971],"ul",{},[297,948,949,952],{},[300,950,951],{},"The dashboard",", for an app with a few parameters. The config form and the targeting rules editor cover everything above.",[297,954,955,958,959,962,963,966,967,970],{},[300,956,957],{},"The Terraform provider",", if you want the configuration as code from the start. The ",[285,960,961],{"href":243},"ConfigDirector Terraform provider"," has ",[305,964,965],{},"configdirector_config"," for the config and ",[305,968,969],{},"configdirector_config_targeting_rules"," for the rules of each environment.",[297,972,973,976,977,979],{},[300,974,975],{},"The MCP server",", for a template with many parameters. Connect the ",[285,978,570],{"href":248}," to your coding assistant, give it the exported template, and ask it to create the configs and their targeting rules. Review what it created in the dashboard before switching any SDK.",[981,982,983],"note",{},"Conditions come first. Create a segment for each Remote Config condition that several parameters share, so the rules that use it stay in one place.",[289,985,987],{"id":986},"switch-the-sdks","Switch the SDKs",[278,989,990],{},"Switch one platform at a time. Pass the parameter's in-app default as the in-code default value, so that a config that is missing, or read before the client is ready, still gives the result users get now.",[356,992,994],{"id":993},"initialize-the-client","Initialize the client",[278,996,997,998,434,1001,1004],{},"Create one client when the app starts, with the client SDK key of the environment the build runs against, and initialize it. Where Remote Config needs ",[305,999,1000],{},"setDefaults",[305,1002,1003],{},"fetchAndActivate",", and a minimum fetch interval, ConfigDirector needs the client and one call:",[1006,1007,1008,1098,1158,1226],"code-group",{},[1009,1010,1015],"pre",{"className":1011,"code":1012,"filename":125,"language":1013,"meta":1014,"style":1014},"language-dart shiki shiki-themes material-theme-lighter github-light github-dark","import 'package:configdirector_flutter_client_sdk\u002Fconfigdirector_flutter_client_sdk.dart';\n\nfinal client = ConfigDirectorClient(clientSdkKey: 'YOUR-CLIENT-SDK-KEY');\n\nawait client.initialize();\n","dart","",[305,1016,1017,1034,1040,1073,1078],{"__ignoreMap":1014},[1018,1019,1022,1026,1030],"span",{"class":1020,"line":1021},"line",1,[1018,1023,1025],{"class":1024},"sw1J6","import",[1018,1027,1029],{"class":1028},"s_sjI"," 'package:configdirector_flutter_client_sdk\u002Fconfigdirector_flutter_client_sdk.dart'",[1018,1031,1033],{"class":1032},"sP7_E",";\n",[1018,1035,1037],{"class":1020,"line":1036},2,[1018,1038,1039],{"emptyLinePlaceholder":9},"\n",[1018,1041,1043,1047,1051,1055,1059,1062,1065,1068,1071],{"class":1020,"line":1042},3,[1018,1044,1046],{"class":1045},"sbsja","final",[1018,1048,1050],{"class":1049},"su5hD"," client ",[1018,1052,1054],{"class":1053},"smGrS","=",[1018,1056,1058],{"class":1057},"sZMiF"," ConfigDirectorClient",[1018,1060,1061],{"class":1049},"(clientSdkKey",[1018,1063,1064],{"class":1053},":",[1018,1066,1067],{"class":1028}," 'YOUR-CLIENT-SDK-KEY'",[1018,1069,1070],{"class":1049},")",[1018,1072,1033],{"class":1032},[1018,1074,1076],{"class":1020,"line":1075},4,[1018,1077,1039],{"emptyLinePlaceholder":9},[1018,1079,1081,1085,1088,1090,1093,1096],{"class":1020,"line":1080},5,[1018,1082,1084],{"class":1083},"sVHd0","await",[1018,1086,1087],{"class":1049}," client",[1018,1089,316],{"class":1032},[1018,1091,800],{"class":1092},"sGLFI",[1018,1094,1095],{"class":1049},"()",[1018,1097,1033],{"class":1032},[1009,1099,1103],{"className":1100,"code":1101,"filename":135,"language":1102,"meta":1014,"style":1014},"language-kotlin shiki shiki-themes material-theme-lighter github-light github-dark","import com.configdirector.ConfigDirectorClient\n\nval client = ConfigDirectorClient(applicationContext, \"YOUR-CLIENT-SDK-KEY\")\n\n\u002F\u002F A suspend function: call it from a coroutine.\nclient.initialize()\n","kotlin",[305,1104,1105,1113,1117,1137,1141,1147],{"__ignoreMap":1014},[1018,1106,1107,1109],{"class":1020,"line":1021},[1018,1108,1025],{"class":1053},[1018,1110,1112],{"class":1111},"sbgvK"," com.configdirector.ConfigDirectorClient\n",[1018,1114,1115],{"class":1020,"line":1036},[1018,1116,1039],{"emptyLinePlaceholder":9},[1018,1118,1119,1122,1124,1126,1128,1131,1134],{"class":1020,"line":1042},[1018,1120,1121],{"class":1053},"val",[1018,1123,1050],{"class":1049},[1018,1125,1054],{"class":1053},[1018,1127,1058],{"class":1092},[1018,1129,1130],{"class":1049},"(applicationContext, ",[1018,1132,1133],{"class":1028},"\"YOUR-CLIENT-SDK-KEY\"",[1018,1135,1136],{"class":1049},")\n",[1018,1138,1139],{"class":1020,"line":1075},[1018,1140,1039],{"emptyLinePlaceholder":9},[1018,1142,1143],{"class":1020,"line":1080},[1018,1144,1146],{"class":1145},"sutJx","\u002F\u002F A suspend function: call it from a coroutine.\n",[1018,1148,1150,1153,1155],{"class":1020,"line":1149},6,[1018,1151,1152],{"class":1049},"client.",[1018,1154,800],{"class":1092},[1018,1156,1157],{"class":1049},"()\n",[1009,1159,1163],{"className":1160,"code":1161,"filename":130,"language":1162,"meta":1014,"style":1014},"language-swift shiki shiki-themes material-theme-lighter github-light github-dark","import ConfigDirector\n\nlet client = try ConfigDirectorClient(clientSDKKey: \"YOUR-CLIENT-SDK-KEY\")\n\nawait client.initialize()\n","swift",[305,1164,1165,1172,1176,1211,1215],{"__ignoreMap":1014},[1018,1166,1167,1169],{"class":1020,"line":1021},[1018,1168,1025],{"class":1083},[1018,1170,1171],{"class":1111}," ConfigDirector\n",[1018,1173,1174],{"class":1020,"line":1036},[1018,1175,1039],{"emptyLinePlaceholder":9},[1018,1177,1178,1181,1183,1185,1188,1191,1194,1197,1199,1203,1206,1209],{"class":1020,"line":1042},[1018,1179,1180],{"class":1024},"let",[1018,1182,1050],{"class":1049},[1018,1184,1054],{"class":1053},[1018,1186,1187],{"class":1083}," try",[1018,1189,1058],{"class":1190},"sptTA",[1018,1192,1193],{"class":1032},"(",[1018,1195,1196],{"class":1190},"clientSDKKey",[1018,1198,1064],{"class":1032},[1018,1200,1202],{"class":1201},"sjJ54"," \"",[1018,1204,1205],{"class":1028},"YOUR-CLIENT-SDK-KEY",[1018,1207,1208],{"class":1201},"\"",[1018,1210,1136],{"class":1032},[1018,1212,1213],{"class":1020,"line":1075},[1018,1214,1039],{"emptyLinePlaceholder":9},[1018,1216,1217,1219,1222,1224],{"class":1020,"line":1080},[1018,1218,1084],{"class":1083},[1018,1220,1221],{"class":1049}," client.",[1018,1223,800],{"class":1190},[1018,1225,1157],{"class":1032},[1009,1227,1231],{"className":1228,"code":1229,"filename":195,"language":1230,"meta":1014,"style":1014},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","import { createClient } from \"@configdirector\u002Fclient-sdk\";\n\nexport const client = createClient(\"YOUR-CLIENT-SDK-KEY\");\n\nawait client.initialize();\n","ts",[305,1232,1233,1258,1262,1290,1294],{"__ignoreMap":1014},[1018,1234,1235,1237,1240,1243,1246,1249,1251,1254,1256],{"class":1020,"line":1021},[1018,1236,1025],{"class":1083},[1018,1238,1239],{"class":1032}," {",[1018,1241,1242],{"class":1049}," createClient",[1018,1244,1245],{"class":1032}," }",[1018,1247,1248],{"class":1083}," from",[1018,1250,1202],{"class":1201},[1018,1252,1253],{"class":1028},"@configdirector\u002Fclient-sdk",[1018,1255,1208],{"class":1201},[1018,1257,1033],{"class":1032},[1018,1259,1260],{"class":1020,"line":1036},[1018,1261,1039],{"emptyLinePlaceholder":9},[1018,1263,1264,1267,1270,1273,1276,1278,1280,1282,1284,1286,1288],{"class":1020,"line":1042},[1018,1265,1266],{"class":1083},"export",[1018,1268,1269],{"class":1045}," const",[1018,1271,1087],{"class":1272},"s_hVV",[1018,1274,1275],{"class":1053}," =",[1018,1277,1242],{"class":1092},[1018,1279,1193],{"class":1049},[1018,1281,1208],{"class":1201},[1018,1283,1205],{"class":1028},[1018,1285,1208],{"class":1201},[1018,1287,1070],{"class":1049},[1018,1289,1033],{"class":1032},[1018,1291,1292],{"class":1020,"line":1075},[1018,1293,1039],{"emptyLinePlaceholder":9},[1018,1295,1296,1298,1300,1302,1304,1306],{"class":1020,"line":1080},[1018,1297,1084],{"class":1083},[1018,1299,1087],{"class":1049},[1018,1301,316],{"class":1032},[1018,1303,800],{"class":1092},[1018,1305,1095],{"class":1049},[1018,1307,1033],{"class":1032},[278,1309,1310,1312],{},[305,1311,800],{}," returns when the first values arrive or after its timeout. If your users are often on poor connections, do not await it: reads return the in-code default value until values arrive, and then the real values, exactly as Remote Config does before the first activate.",[356,1314,1316],{"id":1315},"read-a-value","Read a value",[278,1318,1319],{},"Each read takes the key and the in-code default value, and the default decides the type the value is read as:",[1006,1321,1322,1403,1472,1563],{},[1009,1323,1325],{"className":1011,"code":1324,"filename":125,"language":1013,"meta":1014,"style":1014},"\u002F\u002F Before: remoteConfig.getBool('new_checkout')\nfinal newCheckout = client.getValue('new_checkout', false);\n\n\u002F\u002F Before: remoteConfig.getInt('max_items')\nfinal maxItems = client.getValue('max_items', 20);\n",[305,1326,1327,1332,1364,1368,1373],{"__ignoreMap":1014},[1018,1328,1329],{"class":1020,"line":1021},[1018,1330,1331],{"class":1145},"\u002F\u002F Before: remoteConfig.getBool('new_checkout')\n",[1018,1333,1334,1336,1339,1341,1343,1345,1348,1350,1353,1356,1360,1362],{"class":1020,"line":1036},[1018,1335,1046],{"class":1045},[1018,1337,1338],{"class":1049}," newCheckout ",[1018,1340,1054],{"class":1053},[1018,1342,1087],{"class":1049},[1018,1344,316],{"class":1032},[1018,1346,1347],{"class":1092},"getValue",[1018,1349,1193],{"class":1049},[1018,1351,1352],{"class":1028},"'new_checkout'",[1018,1354,1355],{"class":1032},",",[1018,1357,1359],{"class":1358},"s39Yj"," false",[1018,1361,1070],{"class":1049},[1018,1363,1033],{"class":1032},[1018,1365,1366],{"class":1020,"line":1042},[1018,1367,1039],{"emptyLinePlaceholder":9},[1018,1369,1370],{"class":1020,"line":1075},[1018,1371,1372],{"class":1145},"\u002F\u002F Before: remoteConfig.getInt('max_items')\n",[1018,1374,1375,1377,1380,1382,1384,1386,1388,1390,1393,1395,1399,1401],{"class":1020,"line":1080},[1018,1376,1046],{"class":1045},[1018,1378,1379],{"class":1049}," maxItems ",[1018,1381,1054],{"class":1053},[1018,1383,1087],{"class":1049},[1018,1385,316],{"class":1032},[1018,1387,1347],{"class":1092},[1018,1389,1193],{"class":1049},[1018,1391,1392],{"class":1028},"'max_items'",[1018,1394,1355],{"class":1032},[1018,1396,1398],{"class":1397},"srdBf"," 20",[1018,1400,1070],{"class":1049},[1018,1402,1033],{"class":1032},[1009,1404,1406],{"className":1100,"code":1405,"filename":135,"language":1102,"meta":1014,"style":1014},"\u002F\u002F Before: remoteConfig.getBoolean(\"new_checkout\")\nval newCheckout = client.value(\"new_checkout\", false)\n\n\u002F\u002F Before: remoteConfig.getLong(\"max_items\")\nval maxItems = client.value(\"max_items\", 20)\n",[305,1407,1408,1413,1439,1443,1448],{"__ignoreMap":1014},[1018,1409,1410],{"class":1020,"line":1021},[1018,1411,1412],{"class":1145},"\u002F\u002F Before: remoteConfig.getBoolean(\"new_checkout\")\n",[1018,1414,1415,1417,1419,1421,1423,1426,1428,1431,1433,1437],{"class":1020,"line":1036},[1018,1416,1121],{"class":1053},[1018,1418,1338],{"class":1049},[1018,1420,1054],{"class":1053},[1018,1422,1221],{"class":1049},[1018,1424,1425],{"class":1092},"value",[1018,1427,1193],{"class":1049},[1018,1429,1430],{"class":1028},"\"new_checkout\"",[1018,1432,434],{"class":1049},[1018,1434,1436],{"class":1435},"syTEX","false",[1018,1438,1136],{"class":1049},[1018,1440,1441],{"class":1020,"line":1042},[1018,1442,1039],{"emptyLinePlaceholder":9},[1018,1444,1445],{"class":1020,"line":1075},[1018,1446,1447],{"class":1145},"\u002F\u002F Before: remoteConfig.getLong(\"max_items\")\n",[1018,1449,1450,1452,1454,1456,1458,1460,1462,1465,1467,1470],{"class":1020,"line":1080},[1018,1451,1121],{"class":1053},[1018,1453,1379],{"class":1049},[1018,1455,1054],{"class":1053},[1018,1457,1221],{"class":1049},[1018,1459,1425],{"class":1092},[1018,1461,1193],{"class":1049},[1018,1463,1464],{"class":1028},"\"max_items\"",[1018,1466,434],{"class":1049},[1018,1468,1469],{"class":1397},"20",[1018,1471,1136],{"class":1049},[1009,1473,1475],{"className":1160,"code":1474,"filename":130,"language":1162,"meta":1014,"style":1014},"\u002F\u002F Before: remoteConfig[\"new_checkout\"].boolValue\nlet newCheckout = client.value(for: \"new_checkout\", default: false)\n\n\u002F\u002F Before: remoteConfig[\"max_items\"].numberValue\nlet maxItems = client.value(for: \"max_items\", default: 20)\n",[305,1476,1477,1482,1519,1523,1528],{"__ignoreMap":1014},[1018,1478,1479],{"class":1020,"line":1021},[1018,1480,1481],{"class":1145},"\u002F\u002F Before: remoteConfig[\"new_checkout\"].boolValue\n",[1018,1483,1484,1486,1488,1490,1492,1494,1496,1499,1501,1503,1506,1508,1510,1513,1515,1517],{"class":1020,"line":1036},[1018,1485,1180],{"class":1024},[1018,1487,1338],{"class":1049},[1018,1489,1054],{"class":1053},[1018,1491,1221],{"class":1049},[1018,1493,1425],{"class":1272},[1018,1495,1193],{"class":1032},[1018,1497,1498],{"class":1190},"for",[1018,1500,1064],{"class":1032},[1018,1502,1202],{"class":1201},[1018,1504,1505],{"class":1028},"new_checkout",[1018,1507,1208],{"class":1201},[1018,1509,434],{"class":1049},[1018,1511,1512],{"class":1190},"default",[1018,1514,1064],{"class":1032},[1018,1516,1359],{"class":1435},[1018,1518,1136],{"class":1032},[1018,1520,1521],{"class":1020,"line":1042},[1018,1522,1039],{"emptyLinePlaceholder":9},[1018,1524,1525],{"class":1020,"line":1075},[1018,1526,1527],{"class":1145},"\u002F\u002F Before: remoteConfig[\"max_items\"].numberValue\n",[1018,1529,1530,1532,1534,1536,1538,1540,1542,1544,1546,1548,1551,1553,1555,1557,1559,1561],{"class":1020,"line":1080},[1018,1531,1180],{"class":1024},[1018,1533,1379],{"class":1049},[1018,1535,1054],{"class":1053},[1018,1537,1221],{"class":1049},[1018,1539,1425],{"class":1272},[1018,1541,1193],{"class":1032},[1018,1543,1498],{"class":1190},[1018,1545,1064],{"class":1032},[1018,1547,1202],{"class":1201},[1018,1549,1550],{"class":1028},"max_items",[1018,1552,1208],{"class":1201},[1018,1554,434],{"class":1049},[1018,1556,1512],{"class":1190},[1018,1558,1064],{"class":1032},[1018,1560,1398],{"class":1397},[1018,1562,1136],{"class":1032},[1009,1564,1566],{"className":1228,"code":1565,"filename":195,"language":1230,"meta":1014,"style":1014},"\u002F\u002F Before: getBoolean(remoteConfig, \"new_checkout\")\nconst newCheckout = client.getValue(\"new_checkout\", false);\n\n\u002F\u002F Before: getNumber(remoteConfig, \"max_items\")\nconst maxItems = client.getValue(\"max_items\", 20);\n",[305,1567,1568,1573,1605,1609,1614],{"__ignoreMap":1014},[1018,1569,1570],{"class":1020,"line":1021},[1018,1571,1572],{"class":1145},"\u002F\u002F Before: getBoolean(remoteConfig, \"new_checkout\")\n",[1018,1574,1575,1578,1581,1583,1585,1587,1589,1591,1593,1595,1597,1599,1601,1603],{"class":1020,"line":1036},[1018,1576,1577],{"class":1045},"const",[1018,1579,1580],{"class":1272}," newCheckout",[1018,1582,1275],{"class":1053},[1018,1584,1087],{"class":1049},[1018,1586,316],{"class":1032},[1018,1588,1347],{"class":1092},[1018,1590,1193],{"class":1049},[1018,1592,1208],{"class":1201},[1018,1594,1505],{"class":1028},[1018,1596,1208],{"class":1201},[1018,1598,1355],{"class":1032},[1018,1600,1359],{"class":1435},[1018,1602,1070],{"class":1049},[1018,1604,1033],{"class":1032},[1018,1606,1607],{"class":1020,"line":1042},[1018,1608,1039],{"emptyLinePlaceholder":9},[1018,1610,1611],{"class":1020,"line":1075},[1018,1612,1613],{"class":1145},"\u002F\u002F Before: getNumber(remoteConfig, \"max_items\")\n",[1018,1615,1616,1618,1621,1623,1625,1627,1629,1631,1633,1635,1637,1639,1641,1643],{"class":1020,"line":1080},[1018,1617,1577],{"class":1045},[1018,1619,1620],{"class":1272}," maxItems",[1018,1622,1275],{"class":1053},[1018,1624,1087],{"class":1049},[1018,1626,316],{"class":1032},[1018,1628,1347],{"class":1092},[1018,1630,1193],{"class":1049},[1018,1632,1208],{"class":1201},[1018,1634,1550],{"class":1028},[1018,1636,1208],{"class":1201},[1018,1638,1355],{"class":1032},[1018,1640,1398],{"class":1397},[1018,1642,1070],{"class":1049},[1018,1644,1033],{"class":1032},[278,1646,1647,1648,1651],{},"A JSON parameter that you parsed from ",[305,1649,1650],{},"getString"," is read as JSON directly: pass an object or a map as the default and the SDK returns the parsed value.",[356,1653,1655],{"id":1654},"follow-changes","Follow changes",[278,1657,1658,1659,1662,1663,1665],{},"Remote Config's real-time listener tells you a new template exists, and you call ",[305,1660,1661],{},"activate"," and re-read. ConfigDirector's ",[305,1664,824],{},", and the streams and flows of the mobile SDKs, give you the value itself, first the current one and then every change:",[1006,1667,1668,1723,1787,1846],{},[1009,1669,1671],{"className":1011,"code":1670,"filename":125,"language":1013,"meta":1014,"style":1014},"\u002F\u002F Before: remoteConfig.onConfigUpdated.listen((event) async { await remoteConfig.activate(); ... })\nfinal subscription = client.watch('new_checkout', false).listen((newCheckout) {\n  \u002F\u002F Rebuild with the new value\n});\n",[305,1672,1673,1678,1711,1716],{"__ignoreMap":1014},[1018,1674,1675],{"class":1020,"line":1021},[1018,1676,1677],{"class":1145},"\u002F\u002F Before: remoteConfig.onConfigUpdated.listen((event) async { await remoteConfig.activate(); ... })\n",[1018,1679,1680,1682,1685,1687,1689,1691,1693,1695,1697,1699,1701,1703,1705,1708],{"class":1020,"line":1036},[1018,1681,1046],{"class":1045},[1018,1683,1684],{"class":1049}," subscription ",[1018,1686,1054],{"class":1053},[1018,1688,1087],{"class":1049},[1018,1690,316],{"class":1032},[1018,1692,824],{"class":1092},[1018,1694,1193],{"class":1049},[1018,1696,1352],{"class":1028},[1018,1698,1355],{"class":1032},[1018,1700,1359],{"class":1358},[1018,1702,1070],{"class":1049},[1018,1704,316],{"class":1032},[1018,1706,1707],{"class":1092},"listen",[1018,1709,1710],{"class":1049},"((newCheckout) {\n",[1018,1712,1713],{"class":1020,"line":1042},[1018,1714,1715],{"class":1145},"  \u002F\u002F Rebuild with the new value\n",[1018,1717,1718,1721],{"class":1020,"line":1075},[1018,1719,1720],{"class":1049},"})",[1018,1722,1033],{"class":1032},[1009,1724,1726],{"className":1100,"code":1725,"filename":135,"language":1102,"meta":1014,"style":1014},"\u002F\u002F Before: remoteConfig.addOnConfigUpdateListener(...) then remoteConfig.activate()\nlifecycleScope.launch {\n    client.values(\"new_checkout\", false).collect { newCheckout ->\n        \u002F\u002F Update the UI with the new value\n    }\n}\n",[305,1727,1728,1733,1744,1772,1777,1782],{"__ignoreMap":1014},[1018,1729,1730],{"class":1020,"line":1021},[1018,1731,1732],{"class":1145},"\u002F\u002F Before: remoteConfig.addOnConfigUpdateListener(...) then remoteConfig.activate()\n",[1018,1734,1735,1738,1741],{"class":1020,"line":1036},[1018,1736,1737],{"class":1049},"lifecycleScope.",[1018,1739,1740],{"class":1092},"launch",[1018,1742,1743],{"class":1049}," {\n",[1018,1745,1746,1749,1752,1754,1756,1758,1760,1763,1766,1769],{"class":1020,"line":1042},[1018,1747,1748],{"class":1049},"    client.",[1018,1750,1751],{"class":1092},"values",[1018,1753,1193],{"class":1049},[1018,1755,1430],{"class":1028},[1018,1757,434],{"class":1049},[1018,1759,1436],{"class":1435},[1018,1761,1762],{"class":1049},").",[1018,1764,1765],{"class":1092},"collect",[1018,1767,1768],{"class":1049}," { newCheckout ",[1018,1770,1771],{"class":1045},"->\n",[1018,1773,1774],{"class":1020,"line":1075},[1018,1775,1776],{"class":1145},"        \u002F\u002F Update the UI with the new value\n",[1018,1778,1779],{"class":1020,"line":1080},[1018,1780,1781],{"class":1049},"    }\n",[1018,1783,1784],{"class":1020,"line":1149},[1018,1785,1786],{"class":1049},"}\n",[1009,1788,1790],{"className":1160,"code":1789,"filename":130,"language":1162,"meta":1014,"style":1014},"\u002F\u002F Before: remoteConfig.addOnConfigUpdateListener { ... remoteConfig.activate() }\nfor await newCheckout in client.values(for: \"new_checkout\", default: false) {\n    \u002F\u002F Update the UI with the new value\n}\n",[305,1791,1792,1797,1837,1842],{"__ignoreMap":1014},[1018,1793,1794],{"class":1020,"line":1021},[1018,1795,1796],{"class":1145},"\u002F\u002F Before: remoteConfig.addOnConfigUpdateListener { ... remoteConfig.activate() }\n",[1018,1798,1799,1801,1804,1806,1809,1811,1813,1815,1817,1819,1821,1823,1825,1827,1829,1831,1833,1835],{"class":1020,"line":1036},[1018,1800,1498],{"class":1083},[1018,1802,1803],{"class":1083}," await",[1018,1805,1338],{"class":1049},[1018,1807,1808],{"class":1083},"in",[1018,1810,1221],{"class":1049},[1018,1812,1751],{"class":1272},[1018,1814,1193],{"class":1032},[1018,1816,1498],{"class":1190},[1018,1818,1064],{"class":1032},[1018,1820,1202],{"class":1201},[1018,1822,1505],{"class":1028},[1018,1824,1208],{"class":1201},[1018,1826,434],{"class":1049},[1018,1828,1512],{"class":1190},[1018,1830,1064],{"class":1032},[1018,1832,1359],{"class":1435},[1018,1834,1070],{"class":1032},[1018,1836,1743],{"class":1032},[1018,1838,1839],{"class":1020,"line":1042},[1018,1840,1841],{"class":1145},"    \u002F\u002F Update the UI with the new value\n",[1018,1843,1844],{"class":1020,"line":1075},[1018,1845,1786],{"class":1032},[1009,1847,1849],{"className":1228,"code":1848,"filename":195,"language":1230,"meta":1014,"style":1014},"\u002F\u002F Before: onConfigUpdate(remoteConfig, ...) then activate(remoteConfig)\nclient.watch(\"new_checkout\", false, (newCheckout) => {\n  \u002F\u002F Render with the new value\n});\n",[305,1850,1851,1856,1893,1898],{"__ignoreMap":1014},[1018,1852,1853],{"class":1020,"line":1021},[1018,1854,1855],{"class":1145},"\u002F\u002F Before: onConfigUpdate(remoteConfig, ...) then activate(remoteConfig)\n",[1018,1857,1858,1861,1863,1865,1867,1869,1871,1873,1875,1877,1879,1882,1886,1888,1891],{"class":1020,"line":1036},[1018,1859,1860],{"class":1049},"client",[1018,1862,316],{"class":1032},[1018,1864,824],{"class":1092},[1018,1866,1193],{"class":1049},[1018,1868,1208],{"class":1201},[1018,1870,1505],{"class":1028},[1018,1872,1208],{"class":1201},[1018,1874,1355],{"class":1032},[1018,1876,1359],{"class":1435},[1018,1878,1355],{"class":1032},[1018,1880,1881],{"class":1032}," (",[1018,1883,1885],{"class":1884},"s99_P","newCheckout",[1018,1887,1070],{"class":1032},[1018,1889,1890],{"class":1045}," =>",[1018,1892,1743],{"class":1032},[1018,1894,1895],{"class":1020,"line":1042},[1018,1896,1897],{"class":1145},"  \u002F\u002F Render with the new value\n",[1018,1899,1900,1903,1905],{"class":1020,"line":1075},[1018,1901,1902],{"class":1032},"}",[1018,1904,1070],{"class":1049},[1018,1906,1033],{"class":1032},[278,1908,1909,1910,1912,1913,1916,1917,1920,1921,1924],{},"In Flutter, pair ",[305,1911,824],{}," with a ",[305,1914,1915],{},"StreamBuilder","; in Jetpack Compose, use ",[305,1918,1919],{},"configValue"," from the Compose artifact; in SwiftUI, read the stream in a ",[305,1922,1923],{},"task",". Each SDK page shows the pattern for its framework.",[356,1926,1928],{"id":1927},"give-the-context-what-your-rules-need","Give the context what your rules need",[278,1930,1931,1932,1934],{},"Remote Config knew the country, language, and app version of each installation on its own. ConfigDirector knows the app name and version through the SDK's ",[305,1933,622],{},", and everything else from the context your app provides. Set the traits your targeting rules use, and update the context when the user signs in or out:",[1006,1936,1937,2066,2194,2343],{},[1009,1938,1940],{"className":1011,"code":1939,"filename":125,"language":1013,"meta":1014,"style":1014},"await client.initialize(\n  const ConfigDirectorContext(\n    id: '12345',\n    traits: {'country': 'US', 'language': 'en', 'platform': 'ios'},\n  ),\n);\n\n\u002F\u002F On sign out: an anonymous context\nawait client.updateContext(const ConfigDirectorContext());\n",[305,1941,1942,1955,1965,1978,2019,2026,2032,2037,2043],{"__ignoreMap":1014},[1018,1943,1944,1946,1948,1950,1952],{"class":1020,"line":1021},[1018,1945,1084],{"class":1083},[1018,1947,1087],{"class":1049},[1018,1949,316],{"class":1032},[1018,1951,800],{"class":1092},[1018,1953,1954],{"class":1049},"(\n",[1018,1956,1957,1960,1963],{"class":1020,"line":1036},[1018,1958,1959],{"class":1045},"  const",[1018,1961,1962],{"class":1057}," ConfigDirectorContext",[1018,1964,1954],{"class":1049},[1018,1966,1967,1970,1972,1975],{"class":1020,"line":1042},[1018,1968,1969],{"class":1049},"    id",[1018,1971,1064],{"class":1053},[1018,1973,1974],{"class":1028}," '12345'",[1018,1976,1977],{"class":1032},",\n",[1018,1979,1980,1983,1985,1987,1990,1992,1995,1997,2000,2002,2005,2007,2010,2012,2015,2017],{"class":1020,"line":1075},[1018,1981,1982],{"class":1049},"    traits",[1018,1984,1064],{"class":1053},[1018,1986,1239],{"class":1049},[1018,1988,1989],{"class":1028},"'country'",[1018,1991,1064],{"class":1053},[1018,1993,1994],{"class":1028}," 'US'",[1018,1996,1355],{"class":1032},[1018,1998,1999],{"class":1028}," 'language'",[1018,2001,1064],{"class":1053},[1018,2003,2004],{"class":1028}," 'en'",[1018,2006,1355],{"class":1032},[1018,2008,2009],{"class":1028}," 'platform'",[1018,2011,1064],{"class":1053},[1018,2013,2014],{"class":1028}," 'ios'",[1018,2016,1902],{"class":1049},[1018,2018,1977],{"class":1032},[1018,2020,2021,2024],{"class":1020,"line":1080},[1018,2022,2023],{"class":1049},"  )",[1018,2025,1977],{"class":1032},[1018,2027,2028,2030],{"class":1020,"line":1149},[1018,2029,1070],{"class":1049},[1018,2031,1033],{"class":1032},[1018,2033,2035],{"class":1020,"line":2034},7,[1018,2036,1039],{"emptyLinePlaceholder":9},[1018,2038,2040],{"class":1020,"line":2039},8,[1018,2041,2042],{"class":1145},"\u002F\u002F On sign out: an anonymous context\n",[1018,2044,2046,2048,2050,2052,2055,2057,2059,2061,2064],{"class":1020,"line":2045},9,[1018,2047,1084],{"class":1083},[1018,2049,1087],{"class":1049},[1018,2051,316],{"class":1032},[1018,2053,2054],{"class":1092},"updateContext",[1018,2056,1193],{"class":1049},[1018,2058,1577],{"class":1045},[1018,2060,1962],{"class":1057},[1018,2062,2063],{"class":1049},"())",[1018,2065,1033],{"class":1032},[1009,2067,2069],{"className":1100,"code":2068,"filename":135,"language":1102,"meta":1014,"style":1014},"client.initialize(\n    ConfigDirectorContext.build {\n        id(\"12345\")\n        trait(\"country\", \"US\")\n        trait(\"language\", \"en\")\n        trait(\"platform\", \"android\")\n    },\n)\n\n\u002F\u002F On sign out: an anonymous context\nclient.updateContext(ConfigDirectorContext.build { anonymous(true) })\n",[305,2070,2071,2079,2089,2101,2118,2134,2150,2155,2159,2163,2168],{"__ignoreMap":1014},[1018,2072,2073,2075,2077],{"class":1020,"line":1021},[1018,2074,1152],{"class":1049},[1018,2076,800],{"class":1092},[1018,2078,1954],{"class":1049},[1018,2080,2081,2084,2087],{"class":1020,"line":1036},[1018,2082,2083],{"class":1049},"    ConfigDirectorContext.",[1018,2085,2086],{"class":1092},"build",[1018,2088,1743],{"class":1049},[1018,2090,2091,2094,2096,2099],{"class":1020,"line":1042},[1018,2092,2093],{"class":1092},"        id",[1018,2095,1193],{"class":1049},[1018,2097,2098],{"class":1028},"\"12345\"",[1018,2100,1136],{"class":1049},[1018,2102,2103,2106,2108,2111,2113,2116],{"class":1020,"line":1075},[1018,2104,2105],{"class":1092},"        trait",[1018,2107,1193],{"class":1049},[1018,2109,2110],{"class":1028},"\"country\"",[1018,2112,434],{"class":1049},[1018,2114,2115],{"class":1028},"\"US\"",[1018,2117,1136],{"class":1049},[1018,2119,2120,2122,2124,2127,2129,2132],{"class":1020,"line":1080},[1018,2121,2105],{"class":1092},[1018,2123,1193],{"class":1049},[1018,2125,2126],{"class":1028},"\"language\"",[1018,2128,434],{"class":1049},[1018,2130,2131],{"class":1028},"\"en\"",[1018,2133,1136],{"class":1049},[1018,2135,2136,2138,2140,2143,2145,2148],{"class":1020,"line":1149},[1018,2137,2105],{"class":1092},[1018,2139,1193],{"class":1049},[1018,2141,2142],{"class":1028},"\"platform\"",[1018,2144,434],{"class":1049},[1018,2146,2147],{"class":1028},"\"android\"",[1018,2149,1136],{"class":1049},[1018,2151,2152],{"class":1020,"line":2034},[1018,2153,2154],{"class":1049},"    },\n",[1018,2156,2157],{"class":1020,"line":2039},[1018,2158,1136],{"class":1049},[1018,2160,2161],{"class":1020,"line":2045},[1018,2162,1039],{"emptyLinePlaceholder":9},[1018,2164,2166],{"class":1020,"line":2165},10,[1018,2167,2042],{"class":1145},[1018,2169,2171,2173,2175,2178,2180,2183,2186,2188,2191],{"class":1020,"line":2170},11,[1018,2172,1152],{"class":1049},[1018,2174,2054],{"class":1092},[1018,2176,2177],{"class":1049},"(ConfigDirectorContext.",[1018,2179,2086],{"class":1092},[1018,2181,2182],{"class":1049}," { ",[1018,2184,2185],{"class":1092},"anonymous",[1018,2187,1193],{"class":1049},[1018,2189,2190],{"class":1435},"true",[1018,2192,2193],{"class":1049},") })\n",[1009,2195,2197],{"className":1160,"code":2196,"filename":130,"language":1162,"meta":1014,"style":1014},"await client.initialize(\n    context: ConfigDirectorContext(\n        id: \"12345\",\n        traits: [\"country\": \"US\", \"language\": \"en\", \"platform\": \"ios\"]\n    )\n)\n\n\u002F\u002F On sign out: an anonymous context\nawait client.updateContext(ConfigDirectorContext(isAnonymous: true))\n",[305,2198,2199,2209,2220,2235,2300,2305,2309,2313,2317],{"__ignoreMap":1014},[1018,2200,2201,2203,2205,2207],{"class":1020,"line":1021},[1018,2202,1084],{"class":1083},[1018,2204,1221],{"class":1049},[1018,2206,800],{"class":1190},[1018,2208,1954],{"class":1032},[1018,2210,2211,2214,2216,2218],{"class":1020,"line":1036},[1018,2212,2213],{"class":1190},"    context",[1018,2215,1064],{"class":1032},[1018,2217,1962],{"class":1190},[1018,2219,1954],{"class":1032},[1018,2221,2222,2224,2226,2228,2231,2233],{"class":1020,"line":1042},[1018,2223,2093],{"class":1190},[1018,2225,1064],{"class":1032},[1018,2227,1202],{"class":1201},[1018,2229,2230],{"class":1028},"12345",[1018,2232,1208],{"class":1201},[1018,2234,1977],{"class":1049},[1018,2236,2237,2240,2242,2245,2247,2250,2252,2254,2256,2259,2261,2263,2265,2268,2270,2272,2274,2277,2279,2281,2283,2286,2288,2290,2292,2295,2297],{"class":1020,"line":1075},[1018,2238,2239],{"class":1190},"        traits",[1018,2241,1064],{"class":1032},[1018,2243,2244],{"class":1049}," [",[1018,2246,1208],{"class":1201},[1018,2248,2249],{"class":1028},"country",[1018,2251,1208],{"class":1201},[1018,2253,1064],{"class":1053},[1018,2255,1202],{"class":1201},[1018,2257,2258],{"class":1028},"US",[1018,2260,1208],{"class":1201},[1018,2262,434],{"class":1049},[1018,2264,1208],{"class":1201},[1018,2266,2267],{"class":1028},"language",[1018,2269,1208],{"class":1201},[1018,2271,1064],{"class":1053},[1018,2273,1202],{"class":1201},[1018,2275,2276],{"class":1028},"en",[1018,2278,1208],{"class":1201},[1018,2280,434],{"class":1049},[1018,2282,1208],{"class":1201},[1018,2284,2285],{"class":1028},"platform",[1018,2287,1208],{"class":1201},[1018,2289,1064],{"class":1053},[1018,2291,1202],{"class":1201},[1018,2293,2294],{"class":1028},"ios",[1018,2296,1208],{"class":1201},[1018,2298,2299],{"class":1049},"]\n",[1018,2301,2302],{"class":1020,"line":1080},[1018,2303,2304],{"class":1032},"    )\n",[1018,2306,2307],{"class":1020,"line":1149},[1018,2308,1136],{"class":1032},[1018,2310,2311],{"class":1020,"line":2034},[1018,2312,1039],{"emptyLinePlaceholder":9},[1018,2314,2315],{"class":1020,"line":2039},[1018,2316,2042],{"class":1145},[1018,2318,2319,2321,2323,2325,2327,2330,2332,2335,2337,2340],{"class":1020,"line":2045},[1018,2320,1084],{"class":1083},[1018,2322,1221],{"class":1049},[1018,2324,2054],{"class":1190},[1018,2326,1193],{"class":1032},[1018,2328,2329],{"class":1190},"ConfigDirectorContext",[1018,2331,1193],{"class":1032},[1018,2333,2334],{"class":1190},"isAnonymous",[1018,2336,1064],{"class":1032},[1018,2338,2339],{"class":1435}," true",[1018,2341,2342],{"class":1032},"))\n",[1009,2344,2346],{"className":1228,"code":2345,"filename":195,"language":1230,"meta":1014,"style":1014},"await client.initialize({\n  id: \"12345\",\n  traits: { country: \"US\", language: \"en\", platform: \"web\" },\n});\n\n\u002F\u002F On sign out: an anonymous context\nawait client.updateContext({ anonymous: true });\n",[305,2347,2348,2363,2379,2429,2437,2441,2445],{"__ignoreMap":1014},[1018,2349,2350,2352,2354,2356,2358,2360],{"class":1020,"line":1021},[1018,2351,1084],{"class":1083},[1018,2353,1087],{"class":1049},[1018,2355,316],{"class":1032},[1018,2357,800],{"class":1092},[1018,2359,1193],{"class":1049},[1018,2361,2362],{"class":1032},"{\n",[1018,2364,2365,2369,2371,2373,2375,2377],{"class":1020,"line":1036},[1018,2366,2368],{"class":2367},"skxfh","  id",[1018,2370,1064],{"class":1032},[1018,2372,1202],{"class":1201},[1018,2374,2230],{"class":1028},[1018,2376,1208],{"class":1201},[1018,2378,1977],{"class":1032},[1018,2380,2381,2384,2386,2388,2391,2393,2395,2397,2399,2401,2404,2406,2408,2410,2412,2414,2417,2419,2421,2424,2426],{"class":1020,"line":1042},[1018,2382,2383],{"class":2367},"  traits",[1018,2385,1064],{"class":1032},[1018,2387,1239],{"class":1032},[1018,2389,2390],{"class":2367}," country",[1018,2392,1064],{"class":1032},[1018,2394,1202],{"class":1201},[1018,2396,2258],{"class":1028},[1018,2398,1208],{"class":1201},[1018,2400,1355],{"class":1032},[1018,2402,2403],{"class":2367}," language",[1018,2405,1064],{"class":1032},[1018,2407,1202],{"class":1201},[1018,2409,2276],{"class":1028},[1018,2411,1208],{"class":1201},[1018,2413,1355],{"class":1032},[1018,2415,2416],{"class":2367}," platform",[1018,2418,1064],{"class":1032},[1018,2420,1202],{"class":1201},[1018,2422,2423],{"class":1028},"web",[1018,2425,1208],{"class":1201},[1018,2427,2428],{"class":1032}," },\n",[1018,2430,2431,2433,2435],{"class":1020,"line":1075},[1018,2432,1902],{"class":1032},[1018,2434,1070],{"class":1049},[1018,2436,1033],{"class":1032},[1018,2438,2439],{"class":1020,"line":1080},[1018,2440,1039],{"emptyLinePlaceholder":9},[1018,2442,2443],{"class":1020,"line":1149},[1018,2444,2042],{"class":1145},[1018,2446,2447,2449,2451,2453,2455,2457,2460,2463,2465,2467,2469,2471],{"class":1020,"line":2034},[1018,2448,1084],{"class":1083},[1018,2450,1087],{"class":1049},[1018,2452,316],{"class":1032},[1018,2454,2054],{"class":1092},[1018,2456,1193],{"class":1049},[1018,2458,2459],{"class":1032},"{",[1018,2461,2462],{"class":2367}," anonymous",[1018,2464,1064],{"class":1032},[1018,2466,2339],{"class":1435},[1018,2468,1245],{"class":1032},[1018,2470,1070],{"class":1049},[1018,2472,1033],{"class":1032},[278,2474,2475],{},"A context given without an identifier is anonymous: the values are still evaluated for it, with a stable identifier derived from the SDK instance, and it is never stored or shown in the dashboard.",[356,2477,2479],{"id":2478},"the-sdk-for-each-platform","The SDK for each platform",[361,2481,2482,2492],{},[364,2483,2484],{},[367,2485,2486,2489],{},[370,2487,2488],{},"Firebase Remote Config SDK",[370,2490,2491],{},"ConfigDirector SDK",[377,2493,2494,2506,2515,2524,2541,2550,2567],{},[367,2495,2496,2502],{},[382,2497,2498,2499,1070],{},"Flutter (",[305,2500,2501],{},"firebase_remote_config",[382,2503,2504],{},[285,2505,125],{"href":126},[367,2507,2508,2510],{},[382,2509,135],{},[382,2511,2512,2514],{},[285,2513,135],{"href":136},", for Kotlin and Java, with a Jetpack Compose artifact",[367,2516,2517,2520],{},[382,2518,2519],{},"Apple platforms",[382,2521,2522],{},[285,2523,130],{"href":131},[367,2525,2526,2528],{},[382,2527,195],{},[382,2529,2530,434,2533,434,2535,434,2537,434,2539],{},[285,2531,2532],{"href":101},"JavaScript",[285,2534,105],{"href":106},[285,2536,110],{"href":111},[285,2538,146],{"href":147},[285,2540,151],{"href":152},[367,2542,2543,2546],{},[382,2544,2545],{},"React Native (community library)",[382,2547,2548],{},[285,2549,121],{"href":122},[367,2551,2552,2555],{},[382,2553,2554],{},"Server-side Remote Config",[382,2556,2557,434,2559,434,2561,434,2563,434,2565],{},[285,2558,162],{"href":163},[285,2560,167],{"href":168},[285,2562,172],{"href":173},[285,2564,177],{"href":178},[285,2566,182],{"href":183},[367,2568,2569,2572],{},[382,2570,2571],{},"Unity, C++",[382,2573,2574],{},"Not available",[278,2576,2577,2578,2581],{},"Every platform also has an ",[285,2579,2580],{"href":189},"OpenFeature provider",", if you prefer to code against the vendor-neutral OpenFeature API.",[289,2583,2585],{"id":2584},"verify-then-remove-remote-config","Verify, then remove Remote Config",[278,2587,2588],{},"Once a build reads a config from ConfigDirector:",[945,2590,2591,2599,2606],{},[297,2592,2593,2596,2597,316],{},[300,2594,2595],{},"Evaluation Activity"," on the config shows the values being served in each environment. See ",[285,2598,2595],{"href":65},[297,2600,2601,2603,2604,316],{},[300,2602,74],{}," catch the mistakes a migration makes: a key the app asks for that does not exist, a config read with the wrong type, an in-code default value that drifts from the value served, and the default value served more often than expected. See ",[285,2605,74],{"href":75},[297,2607,2608],{},"For a value you rolled out by percentile, the assignment starts afresh: a user who was in Remote Config's 10% is not necessarily in ConfigDirector's. Switch over at a point in the rollout where that is acceptable, or at 0% or 100%.",[278,2610,2611,2612,2615],{},"Keep Remote Config in the app until the versions that read it have faded from your user base, then remove the dependency and delete the parameters from the template. From then on, the ",[285,2613,2614],{"href":70},"config lifecycle"," tells you when each temporary config has settled and can be removed from the code too.",[2617,2618,2619],"style",{},"html pre.shiki code .sw1J6, html code.shiki .sw1J6{--shiki-light:#F76D47;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sptTA, html code.shiki .sptTA{--shiki-light:#6182B8;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"title":1014,"searchDepth":1036,"depth":1036,"links":2621},[2622,2623,2629,2630,2637],{"id":291,"depth":1036,"text":292},{"id":353,"depth":1036,"text":354,"children":2624},[2625,2626,2627,2628],{"id":358,"depth":1042,"text":359},{"id":586,"depth":1042,"text":587},{"id":729,"depth":1042,"text":730},{"id":777,"depth":1042,"text":778},{"id":905,"depth":1036,"text":906},{"id":986,"depth":1036,"text":987,"children":2631},[2632,2633,2634,2635,2636],{"id":993,"depth":1042,"text":994},{"id":1315,"depth":1042,"text":1316},{"id":1654,"depth":1042,"text":1655},{"id":1927,"depth":1042,"text":1928},{"id":2478,"depth":1042,"text":2479},{"id":2584,"depth":1036,"text":2585},"Move your remote configuration from Firebase Remote Config to ConfigDirector. How parameters, conditions, in-app defaults, and fetch and activate map, how to recreate the parameters, and how to switch the Flutter, Android, iOS, and web SDKs over.","md",null,{"modifiedAt":258},{"title":268,"icon":266},{"title":2644,"description":2645},"Migrating from Firebase Remote Config to ConfigDirector","A step by step guide to moving remote configuration and feature flags from Firebase Remote Config to ConfigDirector. Concept mapping, recreating parameters as configs, switching the Flutter, Android, iOS, and web SDKs, and verifying the result.","ZRFIoYiaHpqQNsF-jV2UGUKfKu8ITVZtcqsE712mCnM",[2648,2640],{"title":263,"path":264,"stem":265,"description":2649,"icon":266,"children":-1},"Move your feature flags from LaunchDarkly to ConfigDirector. How projects, environments, flags, contexts, segments, and rollouts map, how to recreate the flags, and how to switch the SDKs over without a risky release.",1792183991133]