@opendocsdev/cli 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +300 -0
  3. package/dist/bin/opendocs.js +712 -0
  4. package/dist/bin/opendocs.js.map +1 -0
  5. package/dist/templates/api-reference.mdx +308 -0
  6. package/dist/templates/components.mdx +286 -0
  7. package/dist/templates/configuration.mdx +190 -0
  8. package/dist/templates/docs.json +27 -0
  9. package/dist/templates/introduction.mdx +25 -0
  10. package/dist/templates/logo.svg +4 -0
  11. package/dist/templates/quickstart.mdx +59 -0
  12. package/dist/templates/writing-content.mdx +236 -0
  13. package/package.json +92 -0
  14. package/src/engine/astro.config.ts +75 -0
  15. package/src/engine/src/components/Analytics.astro +57 -0
  16. package/src/engine/src/components/ApiPlayground.astro +24 -0
  17. package/src/engine/src/components/Callout.astro +66 -0
  18. package/src/engine/src/components/Card.astro +75 -0
  19. package/src/engine/src/components/CardGroup.astro +29 -0
  20. package/src/engine/src/components/CodeGroup.astro +231 -0
  21. package/src/engine/src/components/CopyButton.astro +179 -0
  22. package/src/engine/src/components/Steps.astro +27 -0
  23. package/src/engine/src/components/Tab.astro +21 -0
  24. package/src/engine/src/components/TableOfContents.astro +119 -0
  25. package/src/engine/src/components/Tabs.astro +135 -0
  26. package/src/engine/src/components/index.ts +107 -0
  27. package/src/engine/src/components/react/ApiPlayground/AuthSection.tsx +91 -0
  28. package/src/engine/src/components/react/ApiPlayground/CodeBlock.tsx +66 -0
  29. package/src/engine/src/components/react/ApiPlayground/CodeSnippets.tsx +66 -0
  30. package/src/engine/src/components/react/ApiPlayground/CollapsibleSection.tsx +26 -0
  31. package/src/engine/src/components/react/ApiPlayground/KeyValueEditor.tsx +58 -0
  32. package/src/engine/src/components/react/ApiPlayground/ResponseDisplay.tsx +109 -0
  33. package/src/engine/src/components/react/ApiPlayground/Spinner.tsx +6 -0
  34. package/src/engine/src/components/react/ApiPlayground/constants.ts +16 -0
  35. package/src/engine/src/components/react/ApiPlayground/generators.test.ts +130 -0
  36. package/src/engine/src/components/react/ApiPlayground/generators.ts +75 -0
  37. package/src/engine/src/components/react/ApiPlayground/index.tsx +490 -0
  38. package/src/engine/src/components/react/ApiPlayground/types.ts +35 -0
  39. package/src/engine/src/components/react/Callout.tsx +54 -0
  40. package/src/engine/src/components/react/Card.tsx +48 -0
  41. package/src/engine/src/components/react/CardGroup.tsx +24 -0
  42. package/src/engine/src/components/react/FeedbackWidget.tsx +166 -0
  43. package/src/engine/src/components/react/GitHubLink.tsx +28 -0
  44. package/src/engine/src/components/react/NavigationCard.tsx +53 -0
  45. package/src/engine/src/components/react/PageActions.tsx +124 -0
  46. package/src/engine/src/components/react/PageFooter.tsx +91 -0
  47. package/src/engine/src/components/react/SearchModal.tsx +358 -0
  48. package/src/engine/src/components/react/SearchProvider.tsx +37 -0
  49. package/src/engine/src/components/react/Sidebar.tsx +369 -0
  50. package/src/engine/src/components/react/SidebarSearchTrigger.tsx +57 -0
  51. package/src/engine/src/components/react/Steps.tsx +25 -0
  52. package/src/engine/src/components/react/ThemeToggle.tsx +72 -0
  53. package/src/engine/src/components/react/index.ts +14 -0
  54. package/src/engine/src/env.d.ts +10 -0
  55. package/src/engine/src/layouts/DocsLayout.astro +357 -0
  56. package/src/engine/src/lib/__tests__/markdown.test.ts +124 -0
  57. package/src/engine/src/lib/__tests__/mdx-loader.test.ts +205 -0
  58. package/src/engine/src/lib/config.ts +79 -0
  59. package/src/engine/src/lib/markdown.ts +54 -0
  60. package/src/engine/src/lib/mdx-loader.ts +143 -0
  61. package/src/engine/src/lib/mdx-utils.ts +72 -0
  62. package/src/engine/src/lib/remark-opendocs.ts +195 -0
  63. package/src/engine/src/lib/utils.ts +221 -0
  64. package/src/engine/src/pages/[...slug].astro +115 -0
  65. package/src/engine/src/pages/index.astro +71 -0
  66. package/src/engine/src/scripts/mobile-sidebar.ts +56 -0
  67. package/src/engine/src/scripts/theme-init.ts +25 -0
  68. package/src/engine/src/styles/global.css +703 -0
  69. package/src/engine/tailwind.config.mjs +60 -0
  70. package/src/engine/tsconfig.json +15 -0
  71. package/src/templates/api-reference.mdx +308 -0
  72. package/src/templates/components.mdx +286 -0
  73. package/src/templates/configuration.mdx +190 -0
  74. package/src/templates/docs.json +27 -0
  75. package/src/templates/introduction.mdx +25 -0
  76. package/src/templates/logo.svg +4 -0
  77. package/src/templates/quickstart.mdx +59 -0
  78. package/src/templates/writing-content.mdx +236 -0
@@ -0,0 +1,60 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ export default {
3
+ darkMode: "class",
4
+ content: [
5
+ "./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}",
6
+ // Also scan MDX files from the user's project directory
7
+ `${process.env.OPENDOCS_PROJECT_DIR || "."}/**/*.{md,mdx}`,
8
+ ],
9
+ theme: {
10
+ extend: {
11
+ fontFamily: {
12
+ sans: [
13
+ "Geist Variable",
14
+ "-apple-system",
15
+ "BlinkMacSystemFont",
16
+ "Segoe UI",
17
+ "Roboto",
18
+ "sans-serif",
19
+ ],
20
+ mono: [
21
+ "Geist Mono Variable",
22
+ "ui-monospace",
23
+ "SFMono-Regular",
24
+ "Menlo",
25
+ "Monaco",
26
+ "Consolas",
27
+ "monospace",
28
+ ],
29
+ },
30
+ typography: {
31
+ DEFAULT: {
32
+ css: {
33
+ maxWidth: "none",
34
+ color: "inherit",
35
+ a: {
36
+ color: "var(--color-primary)",
37
+ "&:hover": {
38
+ color: "var(--color-primary-dark)",
39
+ },
40
+ },
41
+ code: {
42
+ backgroundColor: "var(--color-code-inline-bg)",
43
+ color: "var(--color-code-inline-text)",
44
+ borderRadius: "0.25rem",
45
+ padding: "0.125rem 0.375rem",
46
+ fontWeight: "400",
47
+ },
48
+ "code::before": {
49
+ content: '""',
50
+ },
51
+ "code::after": {
52
+ content: '""',
53
+ },
54
+ },
55
+ },
56
+ },
57
+ },
58
+ },
59
+ plugins: [],
60
+ };
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "skipLibCheck": true,
8
+ "esModuleInterop": true,
9
+ "jsx": "react-jsx",
10
+ "jsxImportSource": "react",
11
+ "types": ["node"]
12
+ },
13
+ "include": ["src/**/*", "*.ts", "*.mjs"],
14
+ "exclude": ["node_modules"]
15
+ }
@@ -0,0 +1,308 @@
1
+ ---
2
+ title: API Reference
3
+ description: Example API documentation structure
4
+ ---
5
+
6
+ # API Reference
7
+
8
+ This is an example of how to structure API documentation with opendocs.
9
+
10
+ ## Authentication
11
+
12
+ All API requests require authentication using an API key in the header:
13
+
14
+ ```bash
15
+ curl -H "Authorization: Bearer YOUR_API_KEY" \
16
+ https://api.example.com/v1/users
17
+ ```
18
+
19
+ <Callout type="warning">
20
+ Never expose your API key in client-side code. Always make API calls from your server.
21
+ </Callout>
22
+
23
+ ## Base URL
24
+
25
+ All API endpoints use the following base URL:
26
+
27
+ ```
28
+ https://api.example.com/v1
29
+ ```
30
+
31
+ ## Endpoints
32
+
33
+ ### List Users
34
+
35
+ Retrieve a paginated list of users.
36
+
37
+ ```
38
+ GET /users
39
+ ```
40
+
41
+ **Query Parameters:**
42
+
43
+ | Parameter | Type | Default | Description |
44
+ |-----------|------|---------|-------------|
45
+ | `page` | integer | 1 | Page number |
46
+ | `limit` | integer | 20 | Items per page (max: 100) |
47
+ | `sort` | string | `created_at` | Sort field |
48
+ | `order` | string | `desc` | Sort order (`asc` or `desc`) |
49
+
50
+ **Example Request:**
51
+
52
+ <CodeGroup>
53
+ ```bash cURL
54
+ curl -X GET "https://api.example.com/v1/users?page=1&limit=10" \
55
+ -H "Authorization: Bearer YOUR_API_KEY"
56
+ ```
57
+
58
+ ```javascript JavaScript
59
+ const response = await fetch('https://api.example.com/v1/users?page=1&limit=10', {
60
+ headers: {
61
+ 'Authorization': 'Bearer YOUR_API_KEY'
62
+ }
63
+ });
64
+ const data = await response.json();
65
+ ```
66
+
67
+ ```python Python
68
+ import requests
69
+
70
+ response = requests.get(
71
+ 'https://api.example.com/v1/users',
72
+ params={'page': 1, 'limit': 10},
73
+ headers={'Authorization': 'Bearer YOUR_API_KEY'}
74
+ )
75
+ data = response.json()
76
+ ```
77
+ </CodeGroup>
78
+
79
+ **Example Response:**
80
+
81
+ ```json
82
+ {
83
+ "data": [
84
+ {
85
+ "id": "usr_123",
86
+ "email": "john@example.com",
87
+ "name": "John Doe",
88
+ "created_at": "2024-01-15T10:30:00Z"
89
+ },
90
+ {
91
+ "id": "usr_456",
92
+ "email": "jane@example.com",
93
+ "name": "Jane Smith",
94
+ "created_at": "2024-01-14T08:15:00Z"
95
+ }
96
+ ],
97
+ "pagination": {
98
+ "page": 1,
99
+ "limit": 10,
100
+ "total": 42,
101
+ "total_pages": 5
102
+ }
103
+ }
104
+ ```
105
+
106
+ ---
107
+
108
+ ### Get User
109
+
110
+ Retrieve a single user by ID.
111
+
112
+ ```
113
+ GET /users/:id
114
+ ```
115
+
116
+ **Path Parameters:**
117
+
118
+ | Parameter | Type | Description |
119
+ |-----------|------|-------------|
120
+ | `id` | string | The user ID |
121
+
122
+ **Example Request:**
123
+
124
+ <CodeGroup>
125
+ ```bash cURL
126
+ curl -X GET "https://api.example.com/v1/users/usr_123" \
127
+ -H "Authorization: Bearer YOUR_API_KEY"
128
+ ```
129
+
130
+ ```javascript JavaScript
131
+ const response = await fetch('https://api.example.com/v1/users/usr_123', {
132
+ headers: {
133
+ 'Authorization': 'Bearer YOUR_API_KEY'
134
+ }
135
+ });
136
+ const user = await response.json();
137
+ ```
138
+
139
+ ```python Python
140
+ import requests
141
+
142
+ response = requests.get(
143
+ 'https://api.example.com/v1/users/usr_123',
144
+ headers={'Authorization': 'Bearer YOUR_API_KEY'}
145
+ )
146
+ user = response.json()
147
+ ```
148
+ </CodeGroup>
149
+
150
+ **Example Response:**
151
+
152
+ ```json
153
+ {
154
+ "id": "usr_123",
155
+ "email": "john@example.com",
156
+ "name": "John Doe",
157
+ "avatar_url": "https://example.com/avatars/john.jpg",
158
+ "created_at": "2024-01-15T10:30:00Z",
159
+ "updated_at": "2024-01-20T14:45:00Z"
160
+ }
161
+ ```
162
+
163
+ ---
164
+
165
+ ### Create User
166
+
167
+ Create a new user.
168
+
169
+ ```
170
+ POST /users
171
+ ```
172
+
173
+ **Request Body:**
174
+
175
+ | Field | Type | Required | Description |
176
+ |-------|------|----------|-------------|
177
+ | `email` | string | Yes | User's email address |
178
+ | `name` | string | Yes | User's full name |
179
+ | `password` | string | Yes | Password (min 8 characters) |
180
+
181
+ **Example Request:**
182
+
183
+ <CodeGroup>
184
+ ```bash cURL
185
+ curl -X POST "https://api.example.com/v1/users" \
186
+ -H "Authorization: Bearer YOUR_API_KEY" \
187
+ -H "Content-Type: application/json" \
188
+ -d '{
189
+ "email": "new@example.com",
190
+ "name": "New User",
191
+ "password": "securepassword123"
192
+ }'
193
+ ```
194
+
195
+ ```javascript JavaScript
196
+ const response = await fetch('https://api.example.com/v1/users', {
197
+ method: 'POST',
198
+ headers: {
199
+ 'Authorization': 'Bearer YOUR_API_KEY',
200
+ 'Content-Type': 'application/json'
201
+ },
202
+ body: JSON.stringify({
203
+ email: 'new@example.com',
204
+ name: 'New User',
205
+ password: 'securepassword123'
206
+ })
207
+ });
208
+ const user = await response.json();
209
+ ```
210
+
211
+ ```python Python
212
+ import requests
213
+
214
+ response = requests.post(
215
+ 'https://api.example.com/v1/users',
216
+ headers={
217
+ 'Authorization': 'Bearer YOUR_API_KEY',
218
+ 'Content-Type': 'application/json'
219
+ },
220
+ json={
221
+ 'email': 'new@example.com',
222
+ 'name': 'New User',
223
+ 'password': 'securepassword123'
224
+ }
225
+ )
226
+ user = response.json()
227
+ ```
228
+ </CodeGroup>
229
+
230
+ **Example Response:**
231
+
232
+ ```json
233
+ {
234
+ "id": "usr_789",
235
+ "email": "new@example.com",
236
+ "name": "New User",
237
+ "created_at": "2024-01-21T16:00:00Z"
238
+ }
239
+ ```
240
+
241
+ ---
242
+
243
+ ### Delete User
244
+
245
+ Delete a user by ID.
246
+
247
+ ```
248
+ DELETE /users/:id
249
+ ```
250
+
251
+ <Callout type="error">
252
+ This action is irreversible. All user data will be permanently deleted.
253
+ </Callout>
254
+
255
+ **Example Request:**
256
+
257
+ ```bash
258
+ curl -X DELETE "https://api.example.com/v1/users/usr_123" \
259
+ -H "Authorization: Bearer YOUR_API_KEY"
260
+ ```
261
+
262
+ **Response:** `204 No Content`
263
+
264
+ ## Error Handling
265
+
266
+ The API returns standard HTTP status codes and JSON error responses.
267
+
268
+ **Error Response Format:**
269
+
270
+ ```json
271
+ {
272
+ "error": {
273
+ "code": "invalid_request",
274
+ "message": "The email field is required.",
275
+ "field": "email"
276
+ }
277
+ }
278
+ ```
279
+
280
+ ### Status Codes
281
+
282
+ | Code | Description |
283
+ |------|-------------|
284
+ | `200` | Success |
285
+ | `201` | Created |
286
+ | `204` | No Content |
287
+ | `400` | Bad Request - Invalid parameters |
288
+ | `401` | Unauthorized - Invalid or missing API key |
289
+ | `403` | Forbidden - Insufficient permissions |
290
+ | `404` | Not Found - Resource doesn't exist |
291
+ | `429` | Too Many Requests - Rate limit exceeded |
292
+ | `500` | Internal Server Error |
293
+
294
+ ## Rate Limiting
295
+
296
+ API requests are limited to **100 requests per minute** per API key.
297
+
298
+ Rate limit headers are included in all responses:
299
+
300
+ ```
301
+ X-RateLimit-Limit: 100
302
+ X-RateLimit-Remaining: 95
303
+ X-RateLimit-Reset: 1705849200
304
+ ```
305
+
306
+ <Callout type="tip">
307
+ If you need higher rate limits, contact support to discuss enterprise options.
308
+ </Callout>
@@ -0,0 +1,286 @@
1
+ ---
2
+ title: Components
3
+ description: Built-in MDX components to enhance your documentation
4
+ ---
5
+
6
+ # Components
7
+
8
+ opendocs includes several built-in components to create rich, interactive documentation.
9
+
10
+ ## Callout
11
+
12
+ Use callouts to highlight important information, warnings, tips, or errors.
13
+
14
+ <Callout type="info">
15
+
16
+ This is an **info** callout. Use it for general information and notes.
17
+
18
+ </Callout>
19
+
20
+ <Callout type="tip">
21
+
22
+ This is a **tip** callout. Use it for helpful suggestions and best practices.
23
+
24
+ </Callout>
25
+
26
+ <Callout type="warning">
27
+
28
+ This is a **warning** callout. Use it to caution readers about potential issues.
29
+
30
+ </Callout>
31
+
32
+ <Callout type="error">
33
+
34
+ This is an **error** callout. Use it for critical information or common mistakes.
35
+
36
+ </Callout>
37
+
38
+ ```mdx
39
+ <Callout type="info">
40
+ Your message here. Supports **markdown** formatting.
41
+ </Callout>
42
+ ```
43
+
44
+ ### Callout Types
45
+
46
+ | Type | Usage |
47
+ |------|-------|
48
+ | `info` | General information (default) |
49
+ | `tip` | Helpful suggestions |
50
+ | `warning` | Cautions and potential issues |
51
+ | `error` | Critical warnings or common mistakes |
52
+
53
+ ## Code Groups
54
+
55
+ Display code examples in multiple languages or package managers with tabs.
56
+
57
+ <CodeGroup>
58
+ ```javascript JavaScript
59
+ const greeting = "Hello, World!";
60
+ console.log(greeting);
61
+ ```
62
+
63
+ ```python Python
64
+ greeting = "Hello, World!"
65
+ print(greeting)
66
+ ```
67
+
68
+ ```rust Rust
69
+ fn main() {
70
+ println!("Hello, World!");
71
+ }
72
+ ```
73
+ </CodeGroup>
74
+
75
+ ````mdx
76
+ <CodeGroup>
77
+ ```javascript JavaScript
78
+ const greeting = "Hello, World!";
79
+ ```
80
+
81
+ ```python Python
82
+ greeting = "Hello, World!"
83
+ ```
84
+ </CodeGroup>
85
+ ````
86
+
87
+ ## Cards
88
+
89
+ Use cards to create navigation links or highlight features.
90
+
91
+ <CardGroup cols={2}>
92
+ <Card title="Getting Started" description="Learn the basics of opendocs" href="/quickstart" icon="🚀" />
93
+ <Card title="Configuration" description="Customize your documentation site" href="/configuration" icon="⚙️" />
94
+ <Card title="Components" description="Explore built-in MDX components" href="/components" icon="🧩" />
95
+ <Card title="Writing Content" description="Learn how to write effective docs" href="/writing-content" icon="✍️" />
96
+ </CardGroup>
97
+
98
+ ```mdx
99
+ <CardGroup cols={2}>
100
+ <Card
101
+ title="Getting Started"
102
+ description="Learn the basics"
103
+ href="/quickstart"
104
+ icon="🚀"
105
+ />
106
+ <Card
107
+ title="Configuration"
108
+ description="Customize your site"
109
+ href="/configuration"
110
+ icon="⚙️"
111
+ />
112
+ </CardGroup>
113
+ ```
114
+
115
+ ### Card Props
116
+
117
+ | Prop | Type | Description |
118
+ |------|------|-------------|
119
+ | `title` | string | Card title (required) |
120
+ | `description` | string | Short description |
121
+ | `href` | string | Link destination |
122
+ | `icon` | string | Emoji or icon character |
123
+
124
+ ### CardGroup Props
125
+
126
+ | Prop | Type | Default | Description |
127
+ |------|------|---------|-------------|
128
+ | `cols` | 1, 2, 3, 4 | 2 | Number of columns |
129
+
130
+ ## Steps
131
+
132
+ Create numbered step-by-step instructions.
133
+
134
+ <Steps>
135
+
136
+ ### Install the CLI
137
+
138
+ Install opendocs globally using npm, yarn, or pnpm.
139
+
140
+ ### Initialize your project
141
+
142
+ Run `opendocs init my-docs` to create a new documentation project.
143
+
144
+ ### Start the dev server
145
+
146
+ Run `opendocs dev` to preview your documentation locally.
147
+
148
+ ### Deploy
149
+
150
+ Build and deploy your documentation to any static hosting service.
151
+
152
+ </Steps>
153
+
154
+ ```mdx
155
+ <Steps>
156
+
157
+ ### Step One
158
+
159
+ Description for step one.
160
+
161
+ ### Step Two
162
+
163
+ Description for step two.
164
+
165
+ ### Step Three
166
+
167
+ Description for step three.
168
+
169
+ </Steps>
170
+ ```
171
+
172
+ <Callout type="tip">
173
+
174
+ Steps automatically number each child heading (h3, h4, etc.) and display them with a connected timeline.
175
+
176
+ </Callout>
177
+
178
+ ## Combining Components
179
+
180
+ Components can be nested and combined for more complex layouts.
181
+
182
+ ### Steps with Cards
183
+
184
+ Use Cards inside Steps to provide navigation options at each stage:
185
+
186
+ <Steps>
187
+
188
+ ### Choose your setup
189
+
190
+ <CardGroup cols={2}>
191
+ <Card title="Quick Start" description="Get running in minutes" href="/quickstart" icon="⚡" />
192
+ <Card title="Manual Setup" description="Full control over configuration" href="/configuration" icon="🔧" />
193
+ </CardGroup>
194
+
195
+ ### Configure your project
196
+
197
+ <Callout type="info">
198
+
199
+ Edit `docs.json` to customize navigation, theme, and features.
200
+
201
+ </Callout>
202
+
203
+ ### Write your content
204
+
205
+ Create `.mdx` files and start documenting your project.
206
+
207
+ </Steps>
208
+
209
+ ### Cards with Code Examples
210
+
211
+ Combine explanatory cards with code samples:
212
+
213
+ <CardGroup cols={2}>
214
+ <Card title="Frontend" description="React, Vue, or vanilla JS" icon="🖥️" />
215
+ <Card title="Backend" description="Node.js, Python, or Go" icon="⚙️" />
216
+ </CardGroup>
217
+
218
+ <CodeGroup>
219
+ ```javascript React
220
+ import { useState } from 'react';
221
+
222
+ function App() {
223
+ const [count, setCount] = useState(0);
224
+ return <button onClick={() => setCount(count + 1)}>{count}</button>;
225
+ }
226
+ ```
227
+
228
+ ```python FastAPI
229
+ from fastapi import FastAPI
230
+
231
+ app = FastAPI()
232
+
233
+ @app.get("/")
234
+ def read_root():
235
+ return {"Hello": "World"}
236
+ ```
237
+ </CodeGroup>
238
+
239
+ ### Callouts in Context
240
+
241
+ Use callouts within other components to highlight important information:
242
+
243
+ <Steps>
244
+
245
+ ### Install dependencies
246
+
247
+ ```bash
248
+ pnpm install
249
+ ```
250
+
251
+ <Callout type="warning">
252
+
253
+ Make sure you have Node.js 18+ installed before proceeding.
254
+
255
+ </Callout>
256
+
257
+ ### Start development
258
+
259
+ ```bash
260
+ pnpm dev
261
+ ```
262
+
263
+ <Callout type="tip">
264
+
265
+ The dev server supports hot reload - changes appear instantly!
266
+
267
+ </Callout>
268
+
269
+ </Steps>
270
+
271
+ ### Feature Comparison Tables
272
+
273
+ Combine tables with callouts for feature documentation:
274
+
275
+ | Feature | Free | Pro | Enterprise |
276
+ |---------|------|-----|------------|
277
+ | Pages | 10 | 100 | Unlimited |
278
+ | Custom domain | No | Yes | Yes |
279
+ | Analytics | Basic | Advanced | Advanced |
280
+ | Support | Community | Email | Dedicated |
281
+
282
+ <Callout type="info">
283
+
284
+ All plans include search, dark mode, and responsive design.
285
+
286
+ </Callout>