Skip to content

Commit d9a1e7f

Browse files
v0.5 Devdocs: Dockerization implementation and more enhancements in UI. (#29)
Here's what's new: • 🐳 Complete Docker Overhaul - One command now handles everything from setup to monitoring Now you can launch the entire DevDocs ecosystem with a single command and focus on documentation, not setup • 🖥️ True Cross-Platform Support - Carefully crafted scripts for both Unix and Windows Enjoy the same reliable experience whether you're on macOS, Linux, or Windows • 📊 Enhanced Logging & Monitoring - Docker-native logging and comprehensive health checks Easily troubleshoot issues with real-time log streaming and container-specific access • 📚 Improved Documentation - New "Scripts and Their Purpose" section and platform-specific guides Find the right tool for the job without digging through code • 🖼️ Better Project Organization - Dedicated assets directory and standardized script locations Navigate a cleaner repository structure that's easier to maintain • 🔧 Technical Improvements - On-demand MCP model and improved Windows permission handling Experience more efficient resource usage and fewer permission-related errors on Windows ❤️ Thanks to all the contributors and collaborators that helped make this release happen!
1 parent 4fe6a2f commit d9a1e7f

File tree

102 files changed

+7048
-57393
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+7048
-57393
lines changed

.env.template

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Crawl4AI API Token (optional)
2+
# If set, this token will be used for authentication with the Crawl4AI service
3+
# A default demo key is provided for testing, but you may want to change this for production
4+
CRAWL4AI_API_TOKEN=devdocs-demo-key
5+
6+
# Resource limits for Crawl4AI container
7+
# Adjust these values based on your system resources
8+
MAX_CONCURRENT_TASKS=5
9+
10+
# MCP Host (used by containers to communicate with the MCP server on the host)
11+
# By default, this is set to host.docker.internal in the docker-compose.yml file
12+
# For macOS and Windows: Leave this commented out, it will work automatically
13+
# For Linux: If you have connectivity issues, uncomment and set to your host's IP address:
14+
# MCP_HOST=192.168.1.x # Replace with your actual host IP
15+
16+
# Uncomment and set these if you want to use LLM features in Crawl4AI
17+
# OPENAI_API_KEY=
18+
# ANTHROPIC_API_KEY=

Dockerfile.backend

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
docker/dockerfiles/Dockerfile.backend

Dockerfile.frontend

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
docker/dockerfiles/Dockerfile.frontend

Dockerfile.mcp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
docker/dockerfiles/Dockerfile.mcp

README.md

Lines changed: 105 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@
99
</p>
1010

1111
<p align="center">
12-
<a href="#perfect-for">Perfect For</a> •
13-
<a href="#features">Features</a> •
14-
<a href="#why-devdocs">Why DevDocs</a> •
15-
<a href="#getting-started">Getting Started</a> •
16-
<a href="#pricing-comparison">Compare to FireCrawl</a> •
17-
<a href="#join-our-community">Discord</a>
12+
<a href="#-perfect-for">Perfect For</a> •
13+
<a href="#-features">Features</a> •
14+
<a href="#-why-devdocs">Why DevDocs</a> •
15+
<a href="#-getting-started">Getting Started</a> •
16+
<a href="#-scripts-and-their-purpose">Scripts</a> •
17+
<a href="#-pricing-comparison">Compare to FireCrawl</a> •
18+
<a href="#-join-our-community">Discord</a>
1819
</p>
1920
</div>
2021

@@ -90,72 +91,125 @@ DevDocs brings documentation to you. Point it at any tech documentation URL, and
9091

9192
## 🚀 Getting Started
9293

93-
We made using DevDocs extremely easy, no complex documentation to learn DevDocs. (UI is very intuitive and self learning)
94+
DevDocs is designed to be easy to use with Docker, requiring minimal setup for new users.
9495

95-
<ins>Mac & Linux(WSL) Users</ins>
96+
### Prerequisites
9697

98+
- [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/) installed on your system
99+
- Git for cloning the repository
100+
101+
### Quick Start with Docker (Recommended)
102+
103+
For Mac/Linux users:
97104
```bash
98105
# Clone the repository
99106
git clone https://github.com/cyberagiinc/DevDocs.git
100107

101-
# Install all good stuff
108+
# Navigate to the project directory
102109
cd DevDocs
103-
./fast-markdown-mcp/setup.sh
104-
105-
# Run Devdocs, (next time just run ./start.sh as all requirements are already installed)
106-
./start.sh
107110

108-
#logs are located under /logs for
109-
backend.log
110-
frontend.log
111-
mcp.log
111+
# Start all services using Docker
112+
./docker-start.sh
112113
```
113114

114-
Visit `http://localhost:3001` and start scraping and discovering documents!
115+
For Windows users:
116+
```cmd
117+
# Clone the repository
118+
git clone https://github.com/cyberagiinc/DevDocs.git
115119
116-
<ins>Windows Users</ins>
120+
# Navigate to the project directory
121+
cd DevDocs
117122
118-
#### Option 1: Using Batch Scripts (Command Prompt)
123+
# Start all services using Docker
124+
docker-start.bat
125+
```
119126

120-
1. Run the setup script:
121-
```
122-
fast-markdown-mcp\setup.bat
127+
> **Note for Windows Users**: If you encounter permission issues, you may need to run the script as administrator or manually set permissions on the logs, storage, and crawl_results directories. The script uses the `icacls` command to set permissions, which might require elevated privileges on some Windows systems.
128+
>
129+
> **Manually Setting Permissions on Windows**:
130+
>
131+
> If you need to manually set permissions, you can do so using either the Windows GUI or command line:
132+
>
133+
> **Using Windows Explorer**:
134+
> 1. Right-click on each directory (logs, storage, crawl_results)
135+
> 2. Select "Properties"
136+
> 3. Go to the "Security" tab
137+
> 4. Click "Edit" to change permissions
138+
> 5. Click "Add" to add users/groups
139+
> 6. Type "Everyone" and click "Check Names"
140+
> 7. Click "OK"
141+
> 8. Select "Everyone" in the list
142+
> 9. Check "Full control" under "Allow"
143+
> 10. Click "Apply" and "OK"
144+
>
145+
> **Using Command Prompt (as Administrator)**:
146+
> ```cmd
147+
> icacls logs /grant Everyone:F /T
148+
> icacls storage /grant Everyone:F /T
149+
> icacls crawl_results /grant Everyone:F /T
150+
> ```
151+
152+
This single command will:
153+
1. Create all necessary directories
154+
2. Set appropriate permissions
155+
3. Build and start all Docker containers
156+
4. Monitor the services to ensure they're running properly
157+
158+
### Accessing DevDocs
159+
160+
Once the services are running:
161+
- Frontend UI: http://localhost:3001
162+
- Backend API: http://localhost:24125
163+
- Crawl4AI Service: http://localhost:11235
164+
165+
### Logs and Monitoring
166+
167+
When using Docker, logs can be accessed :
168+
169+
1. **Container Logs** (recommended for debugging):
170+
```bash
171+
# View logs from a specific container
172+
docker logs devdocs-frontend
173+
docker logs devdocs-backend
174+
docker logs devdocs-mcp
175+
docker logs devdocs-crawl4ai
176+
177+
# Follow logs in real-time
178+
docker logs -f devdocs-backend
123179
```
124180
125-
2. Start all services:
126-
```
127-
start.bat
128-
```
181+
To stop all services, press `Ctrl+C` in the terminal where docker-start is running.
129182

130-
#### Option 2: Using PowerShell Script
183+
## 📜 Scripts and Their Purpose
131184

132-
1. First, run the setup batch script:
133-
```
134-
fast-markdown-mcp\setup.bat
135-
```
185+
DevDocs includes various utility scripts to help with development, testing, and maintenance. Here's a quick reference:
136186

137-
2. Then start all services using PowerShell:
138-
```powershell
139-
.\start.ps1
140-
```
187+
### Startup Scripts
188+
- `start.sh` / `start.bat` / `start.ps1` - Start all services (frontend, backend, MCP) for local development.
189+
- `docker-start.sh` / `docker-start.bat` - Start all services using Docker containers.
141190

142-
Note: If you encounter execution policy restrictions, you may need to run:
143-
```powershell
144-
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
145-
```
191+
### MCP Server Scripts
192+
- `check_mcp_health.sh` - Verify the MCP server's health and configuration status.
193+
- `restart_and_test_mcp.sh` - Restart Docker containers with updated MCP configuration and test connectivity.
146194

147-
#### Option 3: Using Windows Subsystem for Linux (WSL)
195+
### Crawl4AI Scripts
196+
- `check_crawl4ai.sh` - Check the status and health of the Crawl4AI service.
197+
- `debug_crawl4ai.sh` - Run Crawl4AI in debug mode with verbose logging for troubleshooting.
198+
- `test_crawl4ai.py` - Run tests against the Crawl4AI service to verify functionality.
199+
- `test_from_container.sh` - Test the Crawl4AI service from within a Docker container.
148200

149-
If you prefer a Linux-like environment on Windows:
201+
### Utility Scripts
202+
- `view_result.sh` - Display crawl results in a formatted view.
203+
- `find_empty_folders.sh` - Identify empty directories in the project structure.
204+
- `analyze_empty_folders.sh` - Analyze empty folders and categorize them by risk level.
205+
- `verify_reorganization.sh` - Verify that code reorganization was successful.
150206

151-
1. Install WSL by following the [official instructions](https://docs.microsoft.com/en-us/windows/wsl/install)
152-
2. Open a WSL terminal
153-
3. Navigate to your project directory
154-
4. Run the original Linux scripts:
155-
```bash
156-
./fast-markdown-mcp/setup.sh
157-
./start.sh
158-
```
207+
These scripts are organized in the following directories:
208+
- Root directory: Main scripts for common operations
209+
- `scripts/general/`: General utility scripts
210+
- `scripts/docker/`: Docker-specific scripts
211+
- `scripts/mcp/`: MCP server management scripts
212+
- `scripts/test/`: Testing and verification scripts
159213

160214
## 🌍 Built for Developers, by Developers
161215

@@ -226,7 +280,7 @@ Final Output Construction: The final answer should be organized, directly addres
226280

227281
## 📝 Technology Partners
228282

229-
<img src="image-6.png" width="200" height="100"> <img src="image-7.png" width="250" height="100"> <img src="image-8.png" width="300" height="100">
283+
<img src="assets/image-6.png" width="200" height="100"> <img src="assets/image-7.png" width="250" height="100"> <img src="assets/image-8.png" width="300" height="100">
230284

231285
## Star History
232286

app/api/all-files/route.ts

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import { NextResponse } from 'next/server'
2+
import fs from 'fs/promises'
3+
import path from 'path'
4+
5+
const STORAGE_DIR = path.join(process.cwd(), 'storage/markdown')
6+
7+
export async function GET(request: Request) {
8+
try {
9+
// Only get .md files
10+
const files = await fs.readdir(STORAGE_DIR)
11+
const mdFiles = files.filter(f => f.endsWith('.md'))
12+
const jsonFiles = files.filter(f => f.endsWith('.json'))
13+
14+
// Get disk files
15+
const diskFileDetails = await Promise.all(
16+
mdFiles.map(async (filename) => {
17+
const mdPath = path.join(STORAGE_DIR, filename)
18+
const jsonPath = path.join(STORAGE_DIR, filename.replace('.md', '.json'))
19+
const stats = await fs.stat(mdPath)
20+
const content = await fs.readFile(mdPath, 'utf-8')
21+
22+
// Check if this is a consolidated file by examining the JSON metadata
23+
let isConsolidated = false
24+
let pagesCount = 0
25+
let rootUrl = ''
26+
27+
if (jsonFiles.includes(filename.replace('.md', '.json'))) {
28+
try {
29+
const jsonContent = await fs.readFile(jsonPath, 'utf-8')
30+
const metadata = JSON.parse(jsonContent)
31+
32+
// If the metadata has a "pages" array, it's a consolidated file
33+
if (metadata.pages && Array.isArray(metadata.pages)) {
34+
isConsolidated = true
35+
pagesCount = metadata.pages.length
36+
rootUrl = metadata.root_url || ''
37+
}
38+
} catch (e) {
39+
console.error(`Error reading JSON metadata for ${filename}:`, e)
40+
}
41+
} else {
42+
// Create JSON file if it doesn't exist
43+
const jsonContent = JSON.stringify({
44+
content,
45+
metadata: {
46+
wordCount: content.split(/\s+/).length,
47+
charCount: content.length,
48+
timestamp: stats.mtime
49+
}
50+
}, null, 2)
51+
await fs.writeFile(jsonPath, jsonContent, 'utf-8')
52+
}
53+
54+
// Extract sections to count how many pages are included
55+
if (!pagesCount && isConsolidated) {
56+
// Count sections that start with "## " and have a URL: line after them
57+
const sectionMatches = content.match(/## .+\nURL: .+/g)
58+
pagesCount = sectionMatches ? sectionMatches.length : 0
59+
}
60+
61+
return {
62+
name: filename.replace('.md', ''),
63+
jsonPath,
64+
markdownPath: mdPath,
65+
timestamp: stats.mtime,
66+
size: stats.size,
67+
wordCount: content.split(/\s+/).length,
68+
charCount: content.length,
69+
isConsolidated,
70+
pagesCount: isConsolidated ? pagesCount : 1,
71+
rootUrl: rootUrl || '',
72+
isInMemory: false
73+
}
74+
})
75+
)
76+
77+
// Define interface for in-memory file
78+
interface MemoryFile {
79+
name: string;
80+
path: string;
81+
timestamp: string;
82+
size: number;
83+
wordCount: number;
84+
charCount: number;
85+
isInMemory: boolean;
86+
isJson: boolean;
87+
metadata?: any;
88+
}
89+
90+
// Get in-memory files from the backend
91+
let memoryFiles = []
92+
try {
93+
const memoryResponse = await fetch('http://localhost:24125/api/memory-files')
94+
if (memoryResponse.ok) {
95+
const memoryData = await memoryResponse.json()
96+
if (memoryData.success && Array.isArray(memoryData.files)) {
97+
// Convert in-memory files to the same format as disk files
98+
memoryFiles = memoryData.files
99+
.filter((file: MemoryFile) => !file.isJson) // Only include markdown files
100+
.map((file: MemoryFile) => ({
101+
name: file.name,
102+
jsonPath: file.path.replace('.md', '.json'),
103+
markdownPath: file.path,
104+
timestamp: new Date(file.timestamp),
105+
size: file.size,
106+
wordCount: file.wordCount,
107+
charCount: file.charCount,
108+
isConsolidated: false,
109+
pagesCount: 1,
110+
rootUrl: '',
111+
isInMemory: true
112+
}))
113+
}
114+
}
115+
} catch (e) {
116+
console.error('Error fetching in-memory files:', e)
117+
}
118+
119+
// Combine disk and memory files - return ALL files, not just consolidated ones
120+
const allFiles = [...diskFileDetails, ...memoryFiles]
121+
122+
return NextResponse.json({
123+
success: true,
124+
files: allFiles
125+
})
126+
} catch (error) {
127+
return NextResponse.json(
128+
{ success: false, error: error instanceof Error ? error.message : 'Failed to load files' },
129+
{ status: 500 }
130+
)
131+
}
132+
}

0 commit comments

Comments
 (0)