swadhinbiswas

[email protected]
2026-02-28 02:20:37 +0600 committed NaN years ago
cc54aba
commit cc54aba
2 files changed
+588 -32
β–ΌROADMAP.md
+124-32
6
6
7
7
---
8
8
9
-## 🎯 Phase 1: Foundation & MVP (Current)
9
+## βœ… Phase 1: Foundation & MVP (Completed)
10
10
11
-The goal of this phase is to establish a solid, functional, and secure base architecture that proves the concept of a privacy-first, dual-engine writing assistant.
11
+The goal of this phase was to establish a solid, functional, and secure base architecture.
12
12
13
13
* [x] **Chrome Extension Skeleton:** Manifest V3 setup with React and Vite.
14
14
* [x] **Serverless Backend:** A stateless Hono API deployable to edge networks (Cloudflare/Vercel).
15
15
* [x] **Dual Engine:**
16
- * [x] Local rule-based checks (passive voice, repetition).
17
- * [x] AI-powered checks (OpenAI compatibility) with a strict JSON response format.
16
+ * [x] Local rule-based checks (40+ rules: passive voice, repetition, spacing, apostrophes, clichΓ©s, etc.)
17
+ * [x] AI-powered checks (OpenAI/OpenRouter/Groq/Together/Ollama compatible)
18
18
* [x] **Privacy:** Secure local storage for API keys (`chrome.storage.sync`); no backend logging or databases.
19
19
* [x] **Core UI:** Basic popup for configuration (toggling, setting API key/model).
20
20
* [x] **Content Script MVP:** Text extraction and basic visual highlighting for `input`, `textarea`, and standard `contenteditable` elements.
21
+* [x] **Interactive Tooltips:** Click-to-apply suggestions with ignore and dictionary features.
22
+* [x] **Comprehensive Options Page:** Site-specific settings, dictionary management, data export/import.
23
+* [x] **Docker Self-Hosting:** Complete Docker setup with Ollama support for local LLM.
24
+* [x] **Multi-Provider Support:** 6 AI providers (OpenAI, Groq, OpenRouter, Together, Ollama, Custom).
21
25
22
26
---
23
27
24
-## πŸš€ Phase 2: Enhanced User Experience & Accuracy (Next Steps)
28
+## βœ… Phase 2: Enhanced User Experience (Completed)
29
+
30
+This phase focused on making the extension feature-rich and highly customizable.
31
+
32
+* [x] **Tone & Style Rewriting:**
33
+ * [x] 8 tone options (formal, casual, professional, friendly, concise, detailed, persuasive, neutral)
34
+ * [x] Context menu integration (right-click β†’ Rewrite)
35
+ * [x] Keyboard shortcut (Ctrl+Shift+R / Cmd+Shift+R)
36
+ * [x] Side-by-side text comparison UI
37
+* [x] **Writing Statistics Dashboard:**
38
+ * [x] Word count, character count, sentence count, paragraph count
39
+ * [x] Flesch Reading Ease Score
40
+ * [x] Flesch-Kincaid Grade Level
41
+ * [x] Automated Readability Index (ARI)
42
+ * [x] Vocabulary diversity percentage
43
+ * [x] Reading/speaking time estimates
44
+ * [x] Issue breakdown by type
45
+* [x] **Custom Prompts for AI:**
46
+ * [x] 8 preset prompts (Fix Grammar, Make Formal, Simplify, Summarize, etc.)
47
+ * [x] Prompt categories (grammar, style, creative, professional)
48
+ * [x] Extensible system for user-defined prompts
49
+* [ ] **Better Google Docs Support:** (See implementation guide)
50
+* [ ] **Advanced Highlighting Engine:**
51
+ * [ ] Improve robustness inside complex `contenteditable` editors
52
+ * [ ] Implement reliable inline underlines that move correctly
25
53
26
-This phase focuses on making the extension feel natural, responsive, and highly accurate across a wider variety of modern web applications.
54
+---
27
55
28
-* **Advanced Highlighting Engine:**
29
- * Improve the robustness of highlighting inside complex `contenteditable` editors (like Google Docs, Notion, and rich text webmail).
30
- * Implement reliable inline underlines that move correctly when text is edited or scrolled.
31
-* **Interactive Tooltips:**
32
- * Develop a polished, floating UI when hovering over an issue.
33
- * Enable "Click to Apply" functionality to instantly replace the original text with the suggested correction.
34
- * Allow users to "Ignore" a suggestion or "Add to Dictionary" for false positives.
35
-* **Smarter Local Rules:**
36
- * Expand the local, non-AI rule engine using lightweight natural language processing (NLP) libraries (like `compromise` or a small WASM-based parser) to catch more errors offline and for free.
37
-* **Custom Prompts:** Allow advanced users to customize the system prompt sent to the AI (e.g., "Make my writing sound more professional" or "Translate to UK English").
56
+## πŸš€ Phase 3: Advanced Capabilities (Planned)
57
+
58
+Here we will leverage the AI engine to provide deeper insights and more powerful writing assistance.
59
+
60
+* [ ] **Autocomplete & Prediction:**
61
+ * [ ] Suggest next few words as user types
62
+ * [ ] Context-aware completions
63
+ * [ ] Configurable suggestion length
64
+* [ ] **Contextual Understanding:**
65
+ * [ ] Consider previous paragraphs for consistency
66
+ * [ ] Document-wide tone analysis
67
+ * [ ] Track terminology and style preferences
68
+* [x] **Reading Time Estimates:** (Completed in Phase 2)
69
+* [x] **Vocabulary Diversity Metrics:** (Completed in Phase 2)
70
+* [ ] **Writing Analytics:**
71
+ * [ ] Track writing habits over time
72
+ * [ ] Most used words analysis
73
+ * [ ] Sentence length distribution
74
+ * [ ] Weekly/monthly reports
75
+* [ ] **Smart Suggestions:**
76
+ * [ ] Synonym recommendations for overused words
77
+ * [ ] Transition word suggestions
78
+ * [ ] Genre-specific recommendations
38
79
39
80
---
40
81
41
-## 🧠 Phase 3: Advanced Capabilities & Context
82
+## 🌐 Phase 4: Expansion & Ecosystem (Planned)
42
83
43
-Here, we will leverage the AI engine to provide deeper insights and more powerful writing assistance beyond basic grammar and spelling.
84
+The final phase aims to bring OpenGrammar to every platform where people write.
44
85
45
-* **Tone & Style Adjustments:** Options to rewrite a selected paragraph for a specific tone (e.g., Confident, Friendly, Formal, Concise).
46
-* **Autocomplete & Prediction:** Suggest the next few words or sentences as the user types, similar to advanced editor features.
47
-* **Contextual Understanding:** Allow the AI to consider the surrounding text (or even the page context, if permitted by the user) to provide more accurate suggestions, rather than just analyzing isolated sentences.
48
-* **Writing Statistics:** Provide users with insights into their writing habits (e.g., vocabulary diversity, average readability score) processed entirely locally.
86
+* [ ] **Cross-Browser Support:**
87
+ * [ ] Firefox extension (WebExtensions API)
88
+ * [ ] Safari extension (Safari Web Extension Converter)
89
+ * [ ] Edge extension (Chromium-based)
90
+* [ ] **Desktop Applications:**
91
+ * [ ] Electron-based app for Windows, macOS, Linux
92
+ * [ ] System-wide text input integration
93
+ * [ ] Native messaging for full system access
94
+* [ ] **Developer API:**
95
+ * [ ] Public REST API with authentication
96
+ * [ ] Rate limiting and usage tiers
97
+ * [ ] SDK packages (npm, pip)
98
+ * [ ] API documentation portal
99
+* [ ] **Community Ecosystem:**
100
+ * [ ] Custom rule marketplace
101
+ * [ ] Shared prompt library
102
+ * [ ] Language packs for non-English support
103
+ * [ ] Plugin system for extensibility
49
104
50
105
---
51
106
52
-## 🌐 Phase 4: Expansion & Ecosystem
107
+## πŸ“Š Feature Status Summary
108
+
109
+| Feature | Status | Version |
110
+|---------|--------|---------|
111
+| Grammar Checking | βœ… Complete | v1.0 |
112
+| Multi-Provider AI | βœ… Complete | v2.0 |
113
+| Local LLM (Ollama) | βœ… Complete | v2.0 |
114
+| Interactive Tooltips | βœ… Complete | v1.0 |
115
+| Options Page | βœ… Complete | v1.0 |
116
+| Tone Rewriting | βœ… Complete | v2.1 |
117
+| Writing Statistics | βœ… Complete | v2.1 |
118
+| Custom Prompts | βœ… Complete | v2.1 |
119
+| Google Docs Support | 🚧 In Progress | - |
120
+| Autocomplete | πŸ“‹ Planned | v3.0 |
121
+| Firefox Support | πŸ“‹ Planned | v3.0 |
122
+| Desktop Apps | πŸ“‹ Planned | v4.0 |
123
+| Developer API | πŸ“‹ Planned | v4.0 |
53
124
54
-The final phase aims to bring OpenGrammar to every platform where people write.
125
+---
126
+
127
+## 🀝 How to Help
128
+
129
+We need developers, designers, and testers to make this roadmap a reality!
55
130
56
-* **Cross-Browser Support:**
57
- * Port the extension to Firefox (using WebExtensions API).
58
- * Port the extension to Safari.
59
-* **Desktop Applications:** Create standalone desktop apps for Windows, macOS, and Linux that integrate with system-wide text inputs.
60
-* **Developer API:** Offer a documented, self-hostable API so other developers can integrate the OpenGrammar engine into their own applications.
61
-* **Community Rule Marketplace:** A repository where the community can share and install custom rule sets or AI prompts for specific domains (e.g., legal writing, medical writing, creative fiction).
131
+### Contribution Areas
132
+
133
+1. **Core Features:** Pick a feature from Phase 3 or 4 and implement it
134
+2. **Bug Fixes:** Check the GitHub issues tab
135
+3. **Documentation:** Improve guides, add tutorials
136
+4. **Testing:** Test on different browsers and websites
137
+5. **Translations:** Help localize OpenGrammar for other languages
138
+
139
+### Getting Started
140
+
141
+1. Fork the repository
142
+2. Check `FEATURES_IMPLEMENTATION.md` for implementation guides
143
+3. Create a feature branch
144
+4. Submit a pull request
145
+
146
+If you're interested in contributing, please start a discussion on GitHub or join our Discord server!
62
147
63
148
---
64
149
65
-## 🀝 How to Help
150
+## πŸ“… Release Timeline
151
+
152
+| Version | Target | Features |
153
+|---------|--------|----------|
154
+| v2.1 | Current | Tone rewriting, statistics, custom prompts |
155
+| v3.0 | Q2 2026 | Autocomplete, Firefox support, Google Docs |
156
+| v3.5 | Q3 2026 | Contextual understanding, writing analytics |
157
+| v4.0 | Q4 2026 | Desktop apps, Developer API, Safari support |
66
158
67
-We need developers, designers, and testers to make this roadmap a reality. If you're interested in contributing, please pick an issue from our GitHub repository or start a discussion!
159
+*Timeline is approximate and may change based on community contributions.*
68
160
β–Όopengrammar/FEATURES_IMPLEMENTATION.md
+464-0
1
+# πŸš€ OpenGrammar Feature Implementation Guide
2
+
3
+This document provides implementation details for Phase 2, 3, and 4 features.
4
+
5
+---
6
+
7
+## βœ… Phase 2: Enhanced UX (Completed)
8
+
9
+### 1. Tone & Style Adjustments βœ“
10
+**Status:** Implemented
11
+**Files:** `extension/src/rewrite/`
12
+
13
+**Features:**
14
+- 8 tone options (formal, casual, professional, friendly, concise, detailed, persuasive, neutral)
15
+- Context menu integration (right-click β†’ Rewrite)
16
+- Keyboard shortcut (Ctrl+Shift+R)
17
+- Side-by-side comparison UI
18
+- Apply/Copy buttons
19
+
20
+**Usage:**
21
+```javascript
22
+// Select text β†’ Right-click β†’ "Rewrite with OpenGrammar"
23
+// Or press Ctrl+Shift+R
24
+```
25
+
26
+### 2. Writing Statistics βœ“
27
+**Status:** Implemented
28
+**Files:** `extension/src/stats/`
29
+
30
+**Metrics:**
31
+- Word count, character count, sentence count, paragraph count
32
+- Flesch Reading Ease Score
33
+- Flesch-Kincaid Grade Level
34
+- Automated Readability Index (ARI)
35
+- Vocabulary diversity
36
+- Reading/speaking time estimates
37
+- Issue breakdown by type
38
+
39
+**Usage:**
40
+```javascript
41
+// Access via popup β†’ Statistics tab
42
+// Or future: keyboard shortcut
43
+```
44
+
45
+### 3. Custom Prompts for AI βœ“
46
+**Status:** Implemented (Library)
47
+**Files:** `extension/src/prompts/`
48
+
49
+**Preset Prompts:**
50
+- Fix Grammar
51
+- Make Formal/Casual
52
+- Simplify
53
+- Expand
54
+- Summarize
55
+- British English
56
+- Persuade
57
+
58
+**Next Steps:**
59
+- Add UI for prompt selection in rewrite popup
60
+- Allow users to create custom prompts
61
+- Save favorite prompts to storage
62
+
63
+---
64
+
65
+## πŸ”¨ Phase 3: Advanced Features (Implementation Guide)
66
+
67
+### 4. Better Google Docs Support
68
+
69
+**Implementation Steps:**
70
+
71
+1. **Create Google Docs-specific content script:**
72
+```typescript
73
+// extension/src/content/google-docs.ts
74
+export class GoogleDocsHandler {
75
+ private editorElement: HTMLElement | null = null;
76
+
77
+ findEditor() {
78
+ // Google Docs uses a complex iframe structure
79
+ const iframe = document.querySelector('.docs-texteventtarget-iframe');
80
+ if (iframe) {
81
+ const doc = (iframe as HTMLIFrameElement).contentDocument;
82
+ this.editorElement = doc?.querySelector('.kix-appview-editor');
83
+ }
84
+ }
85
+
86
+ extractText() {
87
+ // Google Docs stores content in paragraph spans
88
+ const paragraphs = this.editorElement?.querySelectorAll('.kix-paragraphrenderer');
89
+ return Array.from(paragraphs || []).map(p => p.textContent).join('\n');
90
+ }
91
+}
92
+```
93
+
94
+2. **Update manifest for iframe access:**
95
+```json
96
+"content_scripts": [
97
+ {
98
+ "matches": ["https://docs.google.com/*"],
99
+ "js": ["src/content/google-docs.ts"],
100
+ "all_frames": true
101
+ }
102
+]
103
+```
104
+
105
+3. **Handle Google Docs-specific events:**
106
+- Listen for `docs-chapter-renderer` events
107
+- Monitor selection changes in iframe
108
+- Position highlights relative to editor viewport
109
+
110
+**Estimated Effort:** 2-3 days
111
+
112
+---
113
+
114
+### 5. Autocomplete & Prediction
115
+
116
+**Implementation:**
117
+
118
+1. **Add autocomplete API endpoint:**
119
+```typescript
120
+// backend/src/index.ts
121
+app.post('/autocomplete', async (c) => {
122
+ const { text, cursor, apiKey, model } = await c.req.json();
123
+
124
+ // Get last 50 characters before cursor
125
+ const context = text.substring(Math.max(0, cursor - 50), cursor);
126
+
127
+ const prompt = `Continue this text naturally (max 20 words):
128
+
129
+Context: ${context}...
130
+
131
+Continuation:`;
132
+
133
+ // Call LLM with max_tokens=20
134
+ const completion = await openai.chat.completions.create({
135
+ messages: [{ role: 'user', content: prompt }],
136
+ model,
137
+ max_tokens: 20,
138
+ temperature: 0.8,
139
+ });
140
+
141
+ return c.json({
142
+ suggestion: completion.choices[0].message.content?.trim(),
143
+ });
144
+});
145
+```
146
+
147
+2. **Add content script autocomplete UI:**
148
+```typescript
149
+// extension/src/content/autocomplete.ts
150
+export class AutocompletePopup {
151
+ private popup: HTMLElement | null = null;
152
+
153
+ showSuggestion(suggestion: string, position: { top: number; left: number }) {
154
+ this.popup = document.createElement('div');
155
+ this.popup.className = 'opengrammar-autocomplete';
156
+ this.popup.innerHTML = `
157
+ <span class="ghost-text">${text}</span>
158
+ <span class="suggestion">${suggestion}</span>
159
+ `;
160
+ // Position at cursor
161
+ }
162
+
163
+ accept() {
164
+ // Insert suggestion at cursor
165
+ }
166
+}
167
+```
168
+
169
+3. **Debounce API calls (300ms after typing stops)**
170
+
171
+**Estimated Effort:** 3-4 days
172
+
173
+---
174
+
175
+### 6. Contextual Understanding
176
+
177
+**Implementation:**
178
+
179
+1. **Add context window to analysis:**
180
+```typescript
181
+// backend/src/analyzer.ts
182
+export async function analyzeWithContext(
183
+ text: string,
184
+ context: {
185
+ previousParagraphs: string[];
186
+ documentType?: string;
187
+ tone?: string;
188
+ }
189
+) {
190
+ const prompt = `Analyze this text considering the context:
191
+
192
+Previous context: ${context.previousParagraphs.join(' ')}
193
+Document type: ${context.documentType || 'general'}
194
+
195
+Text to analyze: ${text}
196
+
197
+Consider consistency with previous content and overall tone.`;
198
+
199
+ // Call LLM with context
200
+}
201
+```
202
+
203
+2. **Store document context in background:**
204
+```typescript
205
+// extension/src/background/index.ts
206
+const documentContexts = new Map<string, {
207
+ text: string;
208
+ timestamp: number;
209
+ tone?: string;
210
+}>();
211
+
212
+// Keep last 5000 characters per domain
213
+chrome.tabs.onActivated.addListener((tab) => {
214
+ // Load context for this tab
215
+});
216
+```
217
+
218
+**Estimated Effort:** 2-3 days
219
+
220
+---
221
+
222
+### 7. Reading Time Estimates βœ“
223
+**Status:** Already implemented in Writing Statistics
224
+
225
+**Current Features:**
226
+- Reading time (200 wpm)
227
+- Speaking time (150 wpm)
228
+
229
+**Enhancements:**
230
+- Add detailed breakdown (by paragraph)
231
+- Show progress indicator while reading
232
+- Add customizable reading speed
233
+
234
+---
235
+
236
+### 8. Vocabulary Diversity Metrics βœ“
237
+**Status:** Already implemented in Writing Statistics
238
+
239
+**Current Features:**
240
+- Unique word count
241
+- Vocabulary diversity percentage
242
+- Average word length
243
+
244
+**Enhancements:**
245
+- Track most used words
246
+- Suggest synonyms for overused words
247
+- Show vocabulary level (basic, intermediate, advanced)
248
+
249
+---
250
+
251
+## 🌐 Phase 4: Expansion (Implementation Guide)
252
+
253
+### 9. Firefox Support
254
+
255
+**Steps:**
256
+
257
+1. **Create Firefox-specific manifest:**
258
+```json
259
+// extension/manifest-firefox.json
260
+{
261
+ "browser_specific_settings": {
262
+ "gecko": {
263
264
+ "strict_min_version": "109.0"
265
+ }
266
+ },
267
+ // Rest same as Chrome manifest
268
+}
269
+```
270
+
271
+2. **Adjust Chrome-specific APIs:**
272
+```typescript
273
+// Use browser polyfill
274
+import browser from 'webextension-polyfill';
275
+
276
+// Replace chrome.* with browser.*
277
+browser.storage.sync.get(...);
278
+browser.contextMenus.create(...);
279
+```
280
+
281
+3. **Add Firefox build script:**
282
+```json
283
+// package.json
284
+"scripts": {
285
+ "build:firefox": "vite build --mode firefox"
286
+}
287
+```
288
+
289
+4. **Test in Firefox:**
290
+- Load temporary add-on in about:debugging
291
+- Submit to Firefox Add-ons
292
+
293
+**Estimated Effort:** 1-2 days
294
+
295
+---
296
+
297
+### 10. Safari Support
298
+
299
+**Steps:**
300
+
301
+1. **Use Xcode to create Safari Web Extension:**
302
+```bash
303
+xcrun safari-web-extension-converter extension/dist/ \
304
+ --project-location ./safari \
305
+ --bundle-identifier com.opengrammar.safari
306
+```
307
+
308
+2. **Adjust manifest for Safari:**
309
+- Some Chrome APIs not supported
310
+- May need native app for full functionality
311
+
312
+3. **Create macOS app wrapper:**
313
+- Swift app to host extension
314
+- Notarize for App Store distribution
315
+
316
+**Estimated Effort:** 3-5 days
317
+
318
+---
319
+
320
+### 11. Desktop Apps
321
+
322
+**Implementation:**
323
+
324
+1. **Use Electron for cross-platform desktop app:**
325
+```bash
326
+npm install electron
327
+```
328
+
329
+2. **Create Electron main process:**
330
+```typescript
331
+// desktop/main.ts
332
+import { app, BrowserWindow } from 'electron';
333
+
334
+function createWindow() {
335
+ const win = new BrowserWindow({
336
+ width: 800,
337
+ height: 600,
338
+ webPreferences: {
339
+ nodeIntegration: true,
340
+ },
341
+ });
342
+
343
+ win.loadURL('https://opengrammar.app');
344
+}
345
+
346
+app.whenReady().then(createWindow);
347
+```
348
+
349
+3. **Integrate with system-wide text inputs:**
350
+- Use native messaging for system-wide support
351
+- Create keyboard shortcut for global access
352
+
353
+**Estimated Effort:** 5-7 days
354
+
355
+---
356
+
357
+### 12. Developer API
358
+
359
+**Implementation:**
360
+
361
+1. **Add API key management:**
362
+```typescript
363
+// backend/src/index.ts
364
+app.post('/api/v1/analyze', async (c) => {
365
+ const apiKey = c.req.header('Authorization')?.replace('Bearer ', '');
366
+
367
+ // Validate API key against database
368
+ const user = await validateApiKey(apiKey);
369
+ if (!user) {
370
+ return c.json({ error: 'Invalid API key' }, 401);
371
+ }
372
+
373
+ // Process request
374
+ const { text } = await c.req.json();
375
+ const issues = RuleBasedAnalyzer.analyze(text);
376
+
377
+ return c.json({ issues });
378
+});
379
+```
380
+
381
+2. **Add rate limiting:**
382
+```typescript
383
+import { rateLimit } from 'hono-rate-limit';
384
+
385
+app.use('/api/*', rateLimit({
386
+ windowMs: 60 * 1000, // 1 minute
387
+ max: 100, // 100 requests per minute
388
+}));
389
+```
390
+
391
+3. **Create API documentation:**
392
+```markdown
393
+# OpenGrammar API
394
+
395
+## POST /api/v1/analyze
396
+
397
+Analyze text for grammar and style issues.
398
+
399
+### Request
400
+```json
401
+{
402
+ "text": "string",
403
+ "options": {
404
+ "checkGrammar": true,
405
+ "checkStyle": true
406
+ }
407
+}
408
+```
409
+
410
+### Response
411
+```json
412
+{
413
+ "issues": [...],
414
+ "metadata": {...}
415
+}
416
+```
417
+```
418
+
419
+4. **Add SDK packages:**
420
+```bash
421
+npm publish @opengrammar/js
422
+pip publish opengrammar
423
+```
424
+
425
+**Estimated Effort:** 3-4 days
426
+
427
+---
428
+
429
+## πŸ“Š Priority & Timeline
430
+
431
+| Feature | Priority | Effort | Dependencies |
432
+|---------|----------|--------|--------------|
433
+| Google Docs Support | High | 2-3 days | None |
434
+| Autocomplete | High | 3-4 days | None |
435
+| Firefox Support | Medium | 1-2 days | None |
436
+| Developer API | Medium | 3-4 days | Backend updates |
437
+| Contextual Understanding | Medium | 2-3 days | Storage updates |
438
+| Desktop Apps | Low | 5-7 days | None |
439
+| Safari Support | Low | 3-5 days | macOS required |
440
+
441
+**Total Estimated Effort:** 19-28 days
442
+
443
+---
444
+
445
+## 🎯 Next Steps
446
+
447
+1. **Immediate (Week 1):**
448
+ - [ ] Add UI for custom prompts in rewrite popup
449
+ - [ ] Implement Google Docs support
450
+ - [ ] Add autocomplete feature
451
+
452
+2. **Short-term (Week 2-3):**
453
+ - [ ] Build Firefox extension
454
+ - [ ] Add contextual understanding
455
+ - [ ] Create developer API
456
+
457
+3. **Long-term (Month 2+):**
458
+ - [ ] Build desktop apps
459
+ - [ ] Safari extension
460
+ - [ ] Advanced AI features
461
+
462
+---
463
+
464
+**Contributing:** Pick a feature from the list above and create a PR! Each feature includes implementation details to get you started.
0
465