This document provides guidance for Large Language Models (LLMs) on how to contribute to the Quicrawl project while maintaining code quality, consistency, and architectural integrity.
Quicrawl is a versatile Go-based web crawler that provides both HTTP API and CLI interfaces. It's designed with clean architecture principles, separating concerns between service logic, HTTP handlers, and CLI commands.
quicrawl/
├── cmd/ # Entry points
│ ├── cli/main.go # CLI application entry
│ └── server/main.go # HTTP server entry
├── internal/ # Private application code
│ ├── service/ # Core business logic
│ ├── http/ # HTTP handlers and routing
│ └── cli/ # CLI commands and interface
├── main.go # Main entry point
└── go.mod # Go module definition
Follow Standard Go Practices:
- Use
gofmtfor consistent formatting - Follow effective Go naming conventions (CamelCase for public, camelCase for private)
- Write clear, self-documenting code with appropriate comments
- Use meaningful variable and function names
Example of Good Style:
// CrawlResult represents the result of a website crawl
type CrawlResult struct {
URL string `json:"url"`
HTML string `json:"html"`
StatusCode int `json:"status_code"`
Headers map[string][]string `json:"headers"`
Timestamp time.Time `json:"timestamp"`
Error string `json:"error,omitempty"`
}Consistent Error Patterns:
- Always handle errors explicitly
- Provide meaningful error messages with context
- Use structured error responses in HTTP handlers
- Include error details in result structures when appropriate
Example:
result, err := s.service.CrawlWebsite(ctx, url)
if err != nil {
return c.JSON(http.StatusInternalServerError, map[string]string{
"error": err.Error(),
})
}Comment Requirements:
- Public functions and types must have godoc comments
- Complex logic should include inline comments
- API endpoints should be clearly documented
- CLI commands should have helpful descriptions
Example:
// CrawlWebsite crawls a website and returns the HTML content.
// It validates the URL, makes an HTTP request, and processes the response.
// Returns a CrawlResult containing the HTML content and metadata.
func (s *Service) CrawlWebsite(ctx context.Context, targetURL string) (*CrawlResult, error) {
// Implementation...
}Purpose: Contains core business logic and domain models.
Guidelines:
- Keep business logic independent of HTTP/CLI concerns
- Use dependency injection for external dependencies
- Implement proper context handling for cancellation
- Follow single responsibility principle
When Adding New Features:
- Add new methods to the
Servicestruct - Create appropriate result structures
- Handle errors gracefully with meaningful messages
- Consider performance implications (timeouts, concurrency)
Purpose: Handles HTTP requests, routing, and responses.
Guidelines:
- Keep handlers thin - delegate to service layer
- Use consistent request/response structures
- Implement proper HTTP status codes
- Validate input parameters
Request Structure Pattern:
var request struct {
URL string `json:"url"`
Parameter bool `json:"parameter,omitempty"`
}Purpose: Provides command-line interface using Cobra.
Guidelines:
- Use Cobra command structure consistently
- Provide helpful descriptions and examples
- Implement proper flag handling
- Support file output where appropriate
Command Pattern:
cmd := &cobra.Command{
Use: "command [args]",
Short: "Brief description",
Long: `Detailed description with examples.`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
// Implementation
},
}Process:
- Add method to service layer with proper error handling
- Create HTTP handler that delegates to service
- Add CLI command if applicable
- Update routing in
SetupRoutes - Test the implementation
Example Workflow:
// 1. Service method
func (s *Service) NewFeature(ctx context.Context, param string) (*Result, error) {
// Implementation
}
// 2. HTTP handler
func (h *Handler) NewFeature(c echo.Context) error {
var request struct {
Param string `json:"param"`
}
// Handle request, call service, return response
}
// 3. Add route
api.POST("/new-feature", h.NewFeature)Critical Rules:
- Never change existing API response structures without versioning
- Add new fields as
omitemptywhen possible - Preserve existing CLI command behavior
- Use feature flags for new functionality
Example of Safe Addition:
type ExistingResult struct {
URL string `json:"url"`
Content string `json:"content"`
// Safe to add new optional fields
NewField string `json:"new_field,omitempty"`
}Current Pattern:
- Configuration is handled in the service constructor
- Use sensible defaults
- Make limits configurable where appropriate
Example:
config := &Config{
MaxResponseSize: 10 * 1024 * 1024, // 10MB
MaxLinksToCrawl: 20,
MaxConcurrency: 10,
MaxHTMLSize: 1024 * 1024, // 1MB
}Requirements:
- Write unit tests for service layer logic
- Test error conditions and edge cases
- Use table-driven tests for multiple scenarios
- Mock external dependencies
Example Test Pattern:
func TestCrawlWebsite(t *testing.T) {
tests := []struct {
name string
url string
expected *CrawlResult
wantErr bool
}{
{
name: "valid URL",
url: "https://example.com",
// expected result
},
// more test cases
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// test implementation
})
}
}Guidelines:
- Test HTTP endpoints with actual requests
- Verify CLI commands work correctly
- Test error scenarios and edge cases
- Ensure proper JSON serialization/deserialization
Current Patterns:
- Use goroutines with semaphores for controlled concurrency
- Implement proper context cancellation
- Handle timeouts appropriately
Example:
semaphore := make(chan struct{}, maxConcurrency)
var wg sync.WaitGroup
for _, item := range items {
wg.Add(1)
go func(item string) {
defer wg.Done()
semaphore <- struct{}{} // Acquire
defer func() { <-semaphore }() // Release
// Process item
}(item)
}
wg.Wait()Guidelines:
- Implement size limits for responses
- Use streaming for large content when possible
- Clean up resources properly
- Consider memory usage in concurrent operations
Requirements:
- Validate all URLs before processing
- Sanitize user input
- Implement rate limiting where appropriate
- Handle malicious content gracefully
Current Protections:
- Maximum response size limits
- Timeout constraints
- Concurrency limits
- HTML size restrictions
Pattern:
- Create new result structure
- Add formatting method to service
- Add parameter to existing endpoints
- Update CLI with new flag
- Maintain backward compatibility
Guidelines:
- Add new methods to service layer
- Implement proper error handling
- Consider resource usage implications
- Provide both HTTP and CLI interfaces
Approach:
- Enhance error messages with context
- Add structured error responses
- Implement retry logic where appropriate
- Provide debugging information
Before contributing, ensure:
- Code follows Go conventions and project style
- All public functions have godoc comments
- Error handling is consistent and meaningful
- Backward compatibility is maintained
- Both HTTP and CLI interfaces are updated (if applicable)
- Resource limits and timeouts are respected
- Code compiles without warnings
- Basic functionality testing is performed
Here's a complete example of adding a new feature following project patterns:
// 1. Add to service layer
func (s *Service) ExtractMetadata(ctx context.Context, url string) (*MetadataResult, error) {
// Implementation with proper error handling
}
// 2. Add result structure
type MetadataResult struct {
URL string `json:"url"`
Title string `json:"title"`
Description string `json:"description"`
Keywords []string `json:"keywords"`
Timestamp time.Time `json:"timestamp"`
Error string `json:"error,omitempty"`
}
// 3. Add HTTP handler
func (h *Handler) ExtractMetadata(c echo.Context) error {
var request struct {
URL string `json:"url"`
}
// Standard request handling pattern
}
// 4. Add CLI command
func (c *CLI) addMetadataCommand() {
// Standard CLI command pattern
}
// 5. Update routes
api.POST("/extract-metadata", h.ExtractMetadata)- Understand the Codebase: Study the existing patterns and architecture
- Start Small: Begin with minor improvements or bug fixes
- Follow Patterns: Use existing code as templates for new features
- Test Thoroughly: Ensure your changes don't break existing functionality
- Document Changes: Update relevant documentation and comments
- Go Documentation: https://golang.org/doc/
- Echo Framework: https://echo.labstack.com/
- Cobra CLI: https://github.com/spf13/cobra
- Project Repository: https://github.com/ja1code/quicrawl
When contributing to this project:
- Study the existing codebase patterns
- Follow the established architectural principles
- Maintain consistency with existing code style
- Ensure backward compatibility
- Test your changes thoroughly
Remember: The goal is to enhance the project while maintaining its reliability, performance, and usability for both API and CLI users.