Skip to content

Commit e14e7de

Browse files
committed
docs: add nm-base core concept documentation
1 parent d1f1542 commit e14e7de

File tree

1 file changed

+184
-0
lines changed
  • apps/landing/src/app/(detail)/docs/core-concepts/nm-base

1 file changed

+184
-0
lines changed
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
export const metadata = {
2+
title: 'N/M Base',
3+
alternates: {
4+
canonical: '/docs/core-concepts/nm-base',
5+
},
6+
}
7+
8+
# N/M Base
9+
10+
Devup UI uses a custom N/M base numbering system to generate compact, collision-free class names that are optimized for CSS constraints and ad-blocker compatibility.
11+
12+
- **Generates compact class names**: Short, efficient class names like `a`, `b`, `c`
13+
- **Avoids CSS constraints**: Class names never start with digits
14+
- **Prevents ad-blocker conflicts**: Avoids patterns that trigger content blockers
15+
- **Ensures uniqueness**: Each style gets a unique, deterministic class name
16+
- **Optimizes for size**: Minimal class name length for maximum efficiency
17+
18+
## How It Works
19+
20+
### **Base System**
21+
22+
The N/M base system uses two character sets:
23+
24+
- **N Base**: `a-z` (26 characters)
25+
- **M Base**: `a-z` (26 characters)
26+
27+
This creates a base-26 system that can represent any number using only lowercase letters.
28+
29+
### **Number Conversion**
30+
31+
Numbers are converted to N/M base using a two-phase approach:
32+
33+
1. **Zero handling**: Returns 'a' when the number is 0
34+
2. **Base conversion**: Uses base-26 to convert numbers to alphabetic characters
35+
- First digit: Uses N base array (a-z)
36+
- Remaining digits: Uses M base array (a-z)
37+
3. **Ad-blocker conflict prevention**: Changes result to "a-d" if it ends with "ad"
38+
39+
### **Class Name Generation**
40+
41+
Class name generation follows these steps:
42+
43+
1. **Style signature creation**: Combines property, level, value, selector, and style order to create a unique key
44+
2. **File identifier addition**: Converts filename to number for per-file CSS splitting
45+
3. **Hash conversion**: Converts the generated key to a number using a hash function
46+
4. **N/M base conversion**: Converts the hashed number to an alphabetic class name using the N/M base system
47+
5. **Final combination**: Combines file identifier and class number to create the final class name when file identifier exists
48+
49+
## Examples
50+
51+
### **Basic Class Names**
52+
53+
<div
54+
style={{
55+
display: 'grid',
56+
gridTemplateColumns: '1fr 1fr',
57+
gap: '2rem',
58+
marginBottom: '2rem',
59+
alignItems: 'start',
60+
}}
61+
>
62+
<div>
63+
```tsx // Input
64+
<div>
65+
<Box bg="red" />
66+
<Box bg="blue" />
67+
<Box color="white" />
68+
</div>
69+
```
70+
</div>
71+
<div>
72+
```tsx // Output (N/M base class names)
73+
<div>
74+
<Box className="a" /> {/* bg: red */}
75+
<Box className="b" /> {/* bg: blue */}
76+
<Box className="c" /> {/* color: white */}
77+
</div>
78+
```
79+
</div>
80+
</div>
81+
82+
### **Responsive Class Names**
83+
84+
<div
85+
style={{
86+
display: 'grid',
87+
gridTemplateColumns: '1fr 1fr',
88+
gap: '2rem',
89+
marginBottom: '2rem',
90+
alignItems: 'start',
91+
}}
92+
>
93+
<div>
94+
```tsx // Input
95+
<Box w={[100, 200, 300]} />
96+
```
97+
</div>
98+
<div>
99+
```tsx // Output
100+
<Box className="d e f" />
101+
{/* w: 100px, w: 200px, w: 300px */}
102+
```
103+
</div>
104+
</div>
105+
106+
### **Pseudo-selector Class Names**
107+
108+
<div
109+
style={{
110+
display: 'grid',
111+
gridTemplateColumns: '1fr 1fr',
112+
gap: '2rem',
113+
marginBottom: '2rem',
114+
alignItems: 'start',
115+
}}
116+
>
117+
<div>
118+
```tsx
119+
<Box _hover={{ bg: 'red' }} />
120+
```
121+
</div>
122+
<div>
123+
```tsx
124+
<Box className="g" />
125+
{/* .g:hover { background: red; } */}
126+
```
127+
</div>
128+
</div>
129+
130+
### **File-specific Class Names**
131+
132+
<div
133+
style={{
134+
display: 'grid',
135+
gridTemplateColumns: '1fr 1fr',
136+
gap: '2rem',
137+
marginBottom: '2rem',
138+
alignItems: 'start',
139+
}}
140+
>
141+
<div>
142+
```tsx
143+
<div>
144+
<Box bg="red" />
145+
<Box bg="red" />
146+
</div>
147+
```
148+
</div>
149+
<div>
150+
```tsx
151+
<div>
152+
<Box className="a" /> {/* file1.tsx */}
153+
<Box className="a-a" /> {/* file2.tsx */}
154+
</div>
155+
```
156+
</div>
157+
</div>
158+
159+
## Ad-blocker Compatibility
160+
161+
### **Why "ad" is Problematic**
162+
163+
Ad-blockers recognize and block class names containing "ad" patterns as advertisements:
164+
165+
- **Ad-blocker filters**: Classify elements containing "ad" strings as advertisements
166+
- **CSS blocking**: Styles are not applied, causing UI to break
167+
- **Poor user experience**: Unintended style blocking causes layout issues
168+
169+
### **Our Solution**
170+
171+
Devup UI prevents ad-blocker conflicts through the following methods:
172+
173+
- **Pattern avoidance**: Automatically converts class names ending with "ad" to "a-d"
174+
- **Safe character usage**: Uses only `a-z`, `-`, `_` to avoid blocking patterns
175+
- **No numbers**: Ensures class names don't start with digits to comply with CSS constraints
176+
177+
## Advantages
178+
179+
- **Compact class names**: First 26 styles generate single characters like `a`, `b`, `c`
180+
- **Build consistency**: Always generates the same class name for identical input
181+
- **Cache optimization**: Consistent class names improve browser cache efficiency
182+
- **Collision prevention**: Each style has a unique signature to prevent class name collisions
183+
- **Ad-blocker compatibility**: Automatically converts "ad" patterns to "a-d" to prevent blocking
184+
- **CSS constraint compliance**: Class names don't start with digits to comply with CSS rules

0 commit comments

Comments
 (0)