Font licenses are confusing. Can I use this font in my app? Do I need to include attribution? Can I modify it?
I built a decision tree that answers these questions in 5 steps.
The problem
Open-source fonts come with licenses. Common ones:
- SIL Open Font License (OFL)
- Apache License 2.0
- MIT License
- Ubuntu Font License (UFL)
- Bitstream Vera License
Each has different requirements. Reading the full license text takes time. Most users just want to know: “Can I use this?”
The decision tree
Instead of explaining licenses, I ask questions:
flowchart TD
A[Start] --> B{Selling the font file?}
B -->|Yes| C[Check license - some prohibit]
B -->|No| D{Modifying the font?}
D -->|Yes| E{License requires new name?}
D -->|No| F{Embedding in app/PDF?}
E -->|OFL/UFL| G[Must rename modified version]
E -->|MIT/Apache| H[Keep original name OK]
F -->|Yes| I[Most licenses allow this]
F -->|No| J{Using on website?}
J -->|Yes| K[All common licenses allow]
J -->|No| L{Need attribution?}
L -->|Apache/MIT| M[Yes - include license notice]
L -->|OFL| N[No attribution required]
style A fill:#e3f2fd
style C fill:#ffcdd2
style I fill:#c8e6c9
style K fill:#c8e6c9
Five questions cover 95% of use cases.
The data model
Each free font has license metadata:
interface FontLicense {
type: 'OFL' | 'Apache-2.0' | 'MIT' | 'UFL' | 'Bitstream';
url: string; // Link to full license text
attribution: boolean; // Must include attribution?
allowModification: boolean; // Can modify the font?
requireNewName: boolean; // Modified versions need new name?
allowSelling: boolean; // Can sell the font file?
allowEmbedding: boolean; // Can embed in apps/PDFs?
}
This metadata powers the decision tree.
License profiles
Each license type has a consistent profile:
const LICENSE_PROFILES: Record<string, FontLicense> = {
'OFL': {
type: 'OFL',
url: 'https://scripts.sil.org/OFL',
attribution: false, // Not required for use
allowModification: true,
requireNewName: true, // Must rename if modified
allowSelling: false, // Cannot sell font alone
allowEmbedding: true,
},
'Apache-2.0': {
type: 'Apache-2.0',
url: 'https://www.apache.org/licenses/LICENSE-2.0',
attribution: true, // Must include license notice
allowModification: true,
requireNewName: false,
allowSelling: true, // Can sell if you include license
allowEmbedding: true,
},
'MIT': {
type: 'MIT',
url: 'https://opensource.org/licenses/MIT',
attribution: true, // Must include copyright notice
allowModification: true,
requireNewName: false,
allowSelling: true,
allowEmbedding: true,
},
};
The profiles are simplified. Real licenses have more nuance. But for common questions, this covers it.
The UI component
The license checker is a simple component:
function LicenseChecker({ license }: { license: FontLicense }) {
const [useCase, setUseCase] = useState<string | null>(null);
const questions = [
{
id: 'selling',
question: 'Are you selling the font file itself?',
relevant: !license.allowSelling,
answer: license.allowSelling
? 'Allowed with this license'
: 'Not allowed - you cannot sell this font',
},
{
id: 'modifying',
question: 'Are you modifying the font?',
relevant: license.requireNewName,
answer: license.requireNewName
? 'Allowed, but you must use a different name'
: 'Allowed with no restrictions',
},
{
id: 'embedding',
question: 'Embedding in an app, PDF, or document?',
relevant: true,
answer: license.allowEmbedding
? 'Allowed'
: 'Check the full license for restrictions',
},
{
id: 'website',
question: 'Using on a website?',
relevant: true,
answer: 'Allowed',
},
{
id: 'attribution',
question: 'Do you need to include attribution?',
relevant: license.attribution,
answer: license.attribution
? 'Yes - include the license notice'
: 'No attribution required',
},
];
return (
<div className="license-checker">
{questions.map((q) => (
<QuestionCard
key={q.id}
question={q.question}
answer={q.answer}
highlighted={useCase === q.id}
onClick={() => setUseCase(q.id)}
/>
))}
<a href={license.url} target="_blank" rel="noopener">
Read the full {license.type} license
</a>
</div>
);
}
Users click through questions. Each answer is pre-computed based on the license profile.
Common scenarios
The most common questions I get:
“Can I use Inter in my commercial app?” → Yes. OFL allows commercial use.
“Do I need to credit Google Fonts?” → Depends on the font. OFL doesn’t require attribution for use. Apache 2.0 requires including the license.
“Can I modify Roboto and sell it?” → Yes, but you must rename it and include the Apache 2.0 license.
“Can I bundle Source Sans Pro in my product?” → Yes. OFL allows embedding.
The decision tree answers all of these.
Edge cases I don’t cover
Some questions need a lawyer:
- Font subsetting for web use (generally allowed, but nuanced)
- Jurisdiction-specific copyright issues
- Commercial vs non-commercial definitions
- Trademark implications of font names
For these, I link to the full license and suggest consulting legal counsel.
The 50 lines
Here’s the core logic:
type LicenseType = 'OFL' | 'Apache-2.0' | 'MIT' | 'UFL' | 'Bitstream';
interface LicenseInfo {
canSell: boolean;
canModify: boolean;
mustRename: boolean;
mustAttribute: boolean;
canEmbed: boolean;
}
const LICENSES: Record<LicenseType, LicenseInfo> = {
'OFL': { canSell: false, canModify: true, mustRename: true, mustAttribute: false, canEmbed: true },
'Apache-2.0': { canSell: true, canModify: true, mustRename: false, mustAttribute: true, canEmbed: true },
'MIT': { canSell: true, canModify: true, mustRename: false, mustAttribute: true, canEmbed: true },
'UFL': { canSell: false, canModify: true, mustRename: true, mustAttribute: false, canEmbed: true },
'Bitstream': { canSell: false, canModify: true, mustRename: true, mustAttribute: false, canEmbed: true },
};
function checkLicense(type: LicenseType, action: string): string {
const license = LICENSES[type];
switch (action) {
case 'sell':
return license.canSell ? 'Allowed (include license)' : 'Not allowed';
case 'modify':
return license.canModify
? license.mustRename ? 'Allowed (must rename)' : 'Allowed'
: 'Not allowed';
case 'embed':
return license.canEmbed ? 'Allowed' : 'Check license';
case 'website':
return 'Allowed';
case 'attribute':
return license.mustAttribute ? 'Required' : 'Not required';
default:
return 'Check license';
}
}
Under 50 lines. Covers the common cases.
Why not just show the license?
I tried that first. Problems:
- Wall of text: Licenses are long. Users don’t read them.
- Legal jargon: “Derivative works” means what?
- Buried answers: The question “can I sell this?” is answered in paragraph 4, clause 2, subsection b.
The decision tree extracts answers. Users get what they need without parsing legalese.
Tradeoffs
What I gained:
- Users quickly understand what they can do
- Reduced support questions about licensing
- Consistent answers across fonts
What I lost:
- Nuance of full license text
- Edge cases aren’t covered
- Legal accuracy (I’m not a lawyer)
Important caveat: The decision tree is a guide, not legal advice. I link to the full license and recommend consulting a lawyer for complex cases.
Impact
Since adding the license checker:
- Time on font pages increased (users engage with the tool)
- License-related support questions dropped 80%
- More confident font adoption (based on feedback)
Simple tools that answer real questions outperform comprehensive documentation.
For a quick interactive check, use our font license checker.