Branch naming, commit style, and pull request scope conventions for contributing to Fymo.
This page covers how we name branches, write commits, and scope pull requests in this repo. Read it before opening your first PR, it’ll save you a review round trip.
Branches follow the pattern <type>/issue-<N>-<slug>. The type describes the kind of change, feat, fix, perf, or chore. The number is the GitHub issue the branch resolves, and the slug is a short, hyphenated description.
If a change has no tracking issue, a small chore or a dependency bump, drop the issue number. Use just <type>/<slug>, for example chore/security-bump-svelte-devalue.
Open the issue first if one doesn’t exist. The issue number in the branch name is what ties a PR back to the problem it’s solving.
Each pull request maps to a single GitHub issue. Even if two changes touch the same area of the code, keep them separate when they’re logically independent. Give each its own issue and its own PR rather than bundling them together.A storage provider interface and a later accessor built on top of it are two issues and two PRs, not one. This keeps review scoped. A reviewer can judge one change against one stated problem, and reverting a PR won’t take unrelated work down with it.
fix(remote): stop truthy-coercing interpolated auth.enabled in discoveryfeat(storage): add StorageProvider interface, local provider, registryperf(remote): cache signature/type-hint reflection per (module, fn)refactor(build): shared prepare_build_config for fymo build and fymo dev
CI checks the subject line of every non-merge commit against this format and fails the build if it doesn’t match.The scope in parentheses names the module or subsystem a commit touches, things like remote, storage, middleware, or jobs. It’s not the issue number, that already lives in the branch name.
Merge commits are exempt from the format check. GitHub writes their subject line, and it isn’t meant to follow Conventional Commits.
A PR title should state the outcome, not the mechanism. Take “Fail the build when @require_auth ships with zero active auth providers” or “Add a runtime accessor for the configured StorageProvider”. Both say what changed and why, so you shouldn’t need to open the diff to figure that out.Keep a PR to the size of its issue. Say a fix touches three call sites for the same root cause, the same interpolation bug in config, server, and remote discovery. That’s still one PR, since it’s one issue and one cause. A fix that also refactors an unrelated helper along the way is two PRs.
If a PR grows past its original issue while you’re working on it, split it. Open a new issue for the part that doesn’t fit and file a separate PR against that issue.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Fymo","description":"Production-ready Python SSR framework for Svelte 5.","colors":{"primary":"#FF3E00","light":"#FF622E","dark":"#C7300A"},"logo":"https://mintcdn.com/fymo/yIkGTNycGALYthyF/images/logo.png?fit=max\u0026auto=format\u0026n=yIkGTNycGALYthyF\u0026q=85\u0026s=c2a3eef1de48da0a732ef73fabe31604","favicon":"https://mintcdn.com/fymo/AYUIC370yG7jbz1F/images/favicon.png?fit=max\u0026auto=format\u0026n=AYUIC370yG7jbz1F\u0026q=85\u0026s=137fed2665956c1d22d436f5de509ab9","navbar":{"links":[{"href":"https://github.com/Bishwas-py/fymo","label":"GitHub"}]},"footer":{"socials":{"github":"https://github.com/Bishwas-py/fymo"}},"styling":{"latex":true},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"fymo","hasAudioNarration":false,"actualSubdomain":"fymo","customDomains":[],"gitSource":{"type":"github","owner":"bishwas-py","repo":"fymo-docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6ae95c2f9249234afda64f92:success","clientVersion":"0.0.4087","searchFilterCounts":[{"language":"default","tag":"Core Concepts","count":11},{"language":"default","tag":"Contributing","count":4},{"language":"default","tag":"Get Started","count":2},{"language":"default","tag":"Deploy","count":1},{"language":"default","tag":"Upgrading","count":1}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"comment-mode","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"contribution-workflow","slug":"/contribution-workflow","pageMetadata":{"title":"Contribution Workflow","description":"Branch naming, commit style, and pull request scope conventions for contributing to Fymo.","href":"/contribution-workflow"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Branch naming, commit style, and pull request scope conventions for contributing to Fymo.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={code:`code`,p:`p`,pre:`pre`,span:`span`,..._provideComponents(),...props.components},{CodeBlock,Heading,Note,Tip,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Note)_missingMdxReference(`Note`,true);if(!Tip)_missingMdxReference(`Tip`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(_components.p,{children:`This page covers how we name branches, write commits, and scope pull requests in this repo. Read it before opening your first PR, it’ll save you a review round trip.`}),`\n`,_jsx(Heading,{level:`2`,id:`branch-naming`,children:`Branch naming`}),`\n`,_jsxs(_components.p,{children:[`Branches follow the pattern `,_jsx(_components.code,{children:`\u003ctype>/issue-\u003cN>-\u003cslug>`}),`. The type describes the kind of change, feat, fix, perf, or chore. The number is the GitHub issue the branch resolves, and the slug is a short, hyphenated description.`]}),`\n`,_jsx(CodeBlock,{numberOfLines:`4`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`4`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`feat/issue-31-storage-accessor`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`fix/issue-30-typed-config-values`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`perf/issue-13-remote-fn-reflection-cache`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsxs(_components.p,{children:[`If a change has no tracking issue, a small chore or a dependency bump, drop the issue number. Use just `,_jsx(_components.code,{children:`\u003ctype>/\u003cslug>`}),`, for example `,_jsx(_components.code,{children:`chore/security-bump-svelte-devalue`}),`.`]}),`\n`,_jsx(Tip,{children:_jsx(_components.p,{children:`Open the issue first if one doesn’t exist. The issue number in the branch name is what ties a PR back to the problem it’s solving.`})}),`\n`,_jsx(Heading,{level:`2`,id:`one-issue-one-pr`,children:`One issue, one PR`}),`\n`,_jsx(_components.p,{children:`Each pull request maps to a single GitHub issue. Even if two changes touch the same area of the code, keep them separate when they’re logically independent. Give each its own issue and its own PR rather than bundling them together.`}),`\n`,_jsx(_components.p,{children:`A storage provider interface and a later accessor built on top of it are two issues and two PRs, not one. This keeps review scoped. A reviewer can judge one change against one stated problem, and reverting a PR won’t take unrelated work down with it.`}),`\n`,_jsx(Heading,{level:`2`,id:`commit-messages`,children:`Commit messages`}),`\n`,_jsxs(_components.p,{children:[`Commit subjects follow Conventional Commits: `,_jsx(_components.code,{children:`type(scope): description`}),`, lowercase, imperative mood, no trailing period.`]}),`\n`,_jsx(CodeBlock,{numberOfLines:`5`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`5`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`fix(remote): stop truthy-coercing interpolated auth.enabled in discovery`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`feat(storage): add StorageProvider interface, local provider, registry`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`perf(remote): cache signature/type-hint reflection per (module, fn)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`refactor(build): shared prepare_build_config for fymo build and fymo dev`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsx(_components.p,{children:`The allowed types are:`}),`\n`,_jsx(CodeBlock,{numberOfLines:`2`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsx(_components.p,{children:`CI checks the subject line of every non-merge commit against this format and fails the build if it doesn’t match.`}),`\n`,_jsx(_components.p,{children:`The scope in parentheses names the module or subsystem a commit touches, things like remote, storage, middleware, or jobs. It’s not the issue number, that already lives in the branch name.`}),`\n`,_jsx(Note,{children:_jsx(_components.p,{children:`Merge commits are exempt from the format check. GitHub writes their subject line, and it isn’t meant to follow Conventional Commits.`})}),`\n`,_jsx(Heading,{level:`2`,id:`pr-scope`,children:`PR scope`}),`\n`,_jsx(_components.p,{children:`A PR title should state the outcome, not the mechanism. Take “Fail the build when @require_auth ships with zero active auth providers” or “Add a runtime accessor for the configured StorageProvider”. Both say what changed and why, so you shouldn’t need to open the diff to figure that out.`}),`\n`,_jsx(_components.p,{children:`Keep a PR to the size of its issue. Say a fix touches three call sites for the same root cause, the same interpolation bug in config, server, and remote discovery. That’s still one PR, since it’s one issue and one cause. A fix that also refactors an unrelated helper along the way is two PRs.`}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`If a PR grows past its original issue while you’re working on it, split it. Open a new issue for the part that doesn’t fit and file a separate PR against that issue.`})})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Contribution Workflow","description":"Branch naming, commit style, and pull request scope conventions for contributing to Fymo.","href":"/contribution-workflow"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Branch naming","slug":"branch-naming","depth":2,"children":[]},{"title":"One issue, one PR","slug":"one-issue-one-pr","depth":2,"children":[]},{"title":"Commit messages","slug":"commit-messages","depth":2,"children":[]},{"title":"PR scope","slug":"pr-scope","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"fymo","siteName":"Fymo","title":"Contribution Workflow - Fymo","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-07-16T16:05:33.625Z","originalFileLocation":"contribution-workflow.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Branch naming, commit style, and pull request scope conventions for contributing to Fymo.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Fymo\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/fymo/IvmUWZFtPAzYLjFQ/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/fymo/IvmUWZFtPAzYLjFQ/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/fymo/IvmUWZFtPAzYLjFQ/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/fymo/IvmUWZFtPAzYLjFQ/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/fymo/IvmUWZFtPAzYLjFQ/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/fymo/IvmUWZFtPAzYLjFQ/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/fymo/IvmUWZFtPAzYLjFQ/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/fymo/IvmUWZFtPAzYLjFQ/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/fymo/IvmUWZFtPAzYLjFQ/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Contribution Workflow - Fymo\">\u003cmeta data-mint-head property=\"og:description\" content=\"Branch naming, commit style, and pull request scope conventions for contributing to Fymo.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Fymo\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://fymo.mintlify.app/contribution-workflow\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://fymo.mintlify.site/_mintlify/api/og/v2?division=Contributing\u0026amp;title=Contribution+Workflow\u0026amp;description=Branch+naming%2C+commit+style%2C+and+pull+request+scope+conventions+for+contributing+to+Fymo.\u0026amp;theme=40d420929c2b0e40d5724d49\u0026amp;signature=06f7891c7bd634708b36b950fc40036e18a26b17d849be52b53ddd1f14f8fb3f\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Contribution Workflow - Fymo\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Branch naming, commit style, and pull request scope conventions for contributing to Fymo.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://fymo.mintlify.site/_mintlify/api/og/v2?division=Contributing\u0026amp;title=Contribution+Workflow\u0026amp;description=Branch+naming%2C+commit+style%2C+and+pull+request+scope+conventions+for+contributing+to+Fymo.\u0026amp;theme=40d420929c2b0e40d5724d49\u0026amp;signature=06f7891c7bd634708b36b950fc40036e18a26b17d849be52b53ddd1f14f8fb3f\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/fymo/IvmUWZFtPAzYLjFQ/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Fymo\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#FF3E00\">\u003clink data-mint-head rel=\"canonical\" href=\"https://fymo.mintlify.app/contribution-workflow\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/contribution-workflow.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://fymo.mintlify.app/#organization\",\"name\":\"Fymo\",\"url\":\"https://fymo.mintlify.app\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/fymo/yIkGTNycGALYthyF/images/logo.png?fit=max\u0026auto=format\u0026n=yIkGTNycGALYthyF\u0026q=85\u0026s=c2a3eef1de48da0a732ef73fabe31604\"}},{\"@type\":\"WebSite\",\"@id\":\"https://fymo.mintlify.app#website\",\"name\":\"Fymo\",\"url\":\"https://fymo.mintlify.app\",\"publisher\":{\"@id\":\"https://fymo.mintlify.app/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://fymo.mintlify.app/contribution-workflow#webpage\",\"url\":\"https://fymo.mintlify.app/contribution-workflow\",\"name\":\"Contribution Workflow\",\"description\":\"Branch naming, commit style, and pull request scope conventions for contributing to Fymo.\",\"dateModified\":\"2026-07-16T16:05:33.625Z\",\"isPartOf\":{\"@id\":\"https://fymo.mintlify.app#website\"},\"breadcrumb\":{\"@id\":\"https://fymo.mintlify.app/contribution-workflow#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://fymo.mintlify.app/contribution-workflow#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Contributing\",\"item\":\"https://fymo.mintlify.app/development-setup\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Contribution Workflow\",\"item\":\"https://fymo.mintlify.app/contribution-workflow\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://fymo.mintlify.app/contribution-workflow#article\",\"headline\":\"Contribution Workflow\",\"name\":\"Contribution Workflow\",\"description\":\"Branch naming, commit style, and pull request scope conventions for contributing to Fymo.\",\"url\":\"https://fymo.mintlify.app/contribution-workflow\",\"mainEntityOfPage\":{\"@id\":\"https://fymo.mintlify.app/contribution-workflow#webpage\"},\"dateModified\":\"2026-07-16T16:05:33.625Z\",\"publisher\":{\"@id\":\"https://fymo.mintlify.app/#organization\"},\"isPartOf\":{\"@id\":\"https://fymo.mintlify.app#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Fymo\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Fymo","nav":{"global":null,"groups":[{"group":"Get Started","pages":[{"title":"Introduction","href":"/introduction"},{"title":"Quickstart","href":"/quickstart"}]},{"group":"Core Concepts","pages":[{"title":"The app/ directory","href":"/app-directory"},{"title":"Generators","href":"/generators"},{"title":"Controllers and Routing","href":"/controllers-and-routing"},{"title":"Remote Functions","href":"/remote-functions"},{"title":"Authentication","href":"/auth"},{"title":"Testing Your App","href":"/testing-your-app"},{"title":"Jobs and Broadcasts","href":"/jobs-and-broadcasts"},{"title":"Storage and Media","href":"/storage-and-media"},{"title":"Assets, Fonts, and Static Files","href":"/assets-fonts-and-static-files"},{"title":"Configuration Reference","href":"/configuration"},{"title":"Logging","href":"/logging"}]},{"group":"Deploy","pages":[{"title":"Production Deployment","href":"/deployment"}]},{"group":"Upgrading","pages":[{"title":"Upgrading","href":"/upgrading"}]},{"group":"Contributing","pages":[{"title":"Development Setup","href":"/development-setup"},{"title":"Testing","href":"/testing"},{"title":"Architecture Tour","description":"A package-by-package tour of the fymo/ source tree, for anyone about to read or modify the framework itself.","href":"/architecture-tour"},{"title":"Contribution Workflow","href":"/contribution-workflow"}]}]},"basePath":"","title":"Contribution Workflow - Fymo","buildId":"dpl_FWZhTb2vab28gFGFH4ojka6qEznQ","deploymentId":"dpl_FWZhTb2vab28gFGFH4ojka6qEznQ","dynamics":[],"chunks":[]}