{"id":25121800,"url":"https://github.com/alastairrushworth/blognerd.app","last_synced_at":"2026-05-05T07:32:25.034Z","repository":{"id":274157228,"uuid":"922072174","full_name":"alastairrushworth/blognerd.app","owner":"alastairrushworth","description":"🔎👨‍💻 Search engine for blogs \u0026 RSS feeds","archived":false,"fork":false,"pushed_at":"2025-10-19T08:26:15.000Z","size":42410,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-19T19:42:56.474Z","etag":null,"topics":["blogs","indieweb","rss"],"latest_commit_sha":null,"homepage":"https://blognerd.app","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alastairrushworth.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-01-25T08:37:25.000Z","updated_at":"2025-10-19T08:26:19.000Z","dependencies_parsed_at":"2025-01-25T10:24:48.590Z","dependency_job_id":"fb05fbdd-b65b-46d0-8637-76ac60fa4ab1","html_url":"https://github.com/alastairrushworth/blognerd.app","commit_stats":null,"previous_names":["alastairrushworth/blognerd.app"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/alastairrushworth/blognerd.app","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alastairrushworth%2Fblognerd.app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alastairrushworth%2Fblognerd.app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alastairrushworth%2Fblognerd.app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alastairrushworth%2Fblognerd.app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alastairrushworth","download_url":"https://codeload.github.com/alastairrushworth/blognerd.app/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alastairrushworth%2Fblognerd.app/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32640533,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-04T10:08:07.713Z","status":"online","status_checked_at":"2026-05-05T02:00:06.033Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blogs","indieweb","rss"],"created_at":"2025-02-08T06:37:08.736Z","updated_at":"2026-05-05T07:32:25.029Z","avatar_url":"https://github.com/alastairrushworth.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BlogNerd.app\n\nA semantic search engine for blog posts and RSS feeds, powered by vector embeddings and AI.\n\n## Features\n\n- 🔍 **Semantic Search**: Find blog posts and RSS feeds using natural language queries\n- 📱 **Mobile Responsive**: Optimized for all screen sizes\n- 🏷️ **Content Filtering**: Filter by content type (blogs, academic, news) and time periods\n- 🔗 **RSS Feed Discovery**: Search and discover RSS feeds with export functionality\n- 📊 **Export Options**: Export RSS feeds as OPML or CSV files\n- ⚡ **Fast Search**: Powered by Pinecone vector database and Voyage AI embeddings\n\n## Technology Stack\n\n- **Backend**: Go 1.21 with Gorilla Mux router\n- **Frontend**: Vanilla HTML, CSS, and JavaScript\n- **Vector Database**: Pinecone\n- **Embeddings**: Voyage AI\n- **Deployment**: Docker support included\n\n## Prerequisites\n\n- Go 1.21 or later\n- Pinecone account and API key\n- Voyage AI account and API key\n\n## Installation\n\n1. **Clone the repository**\n   ```bash\n   git clone https://github.com/alastairrushworth/blognerd.app.git\n   cd blognerd.app\n   ```\n\n2. **Install Go dependencies**\n   ```bash\n   go mod download\n   ```\n\n3. **Set up environment variables**\n   ```bash\n   cp .env.example .env\n   ```\n   \n   Edit `.env` and add your API keys:\n   ```\n   PINECONE_API_KEY=your-pinecone-api-key\n   PINECONE_V2_ENVIRONMENT=your-pinecone-environment\n   PINECONE_V2_INDEX=your-pinecone-index-name\n   PINECONE_V2_HOST=your-pinecone-host-url\n   VOYAGE_API_KEY=your-voyage-ai-api-key\n   ```\n\n4. **Run the application**\n   ```bash\n   go run .\n   ```\n   \n   Or build and run:\n   ```bash\n   go build -o blognerd-server\n   ./blognerd-server\n   ```\n\n5. **Open in browser**\n   ```\n   http://localhost:8000\n   ```\n\n## Docker Deployment\n\nBuild and run with Docker:\n\n```bash\ndocker build -t blognerd-app .\ndocker run -p 8000:8000 --env-file .env blognerd-app\n```\n\n## API Endpoints\n\n### Search API\n- `GET /api/search?qry=\u003cquery\u003e\u0026type=\u003cpages|sites\u003e\u0026content=\u003ccontent_type\u003e\u0026time=\u003ctime_filter\u003e`\n- Returns JSON with search results\n\n### Export APIs\n- `GET /api/export/opml?qry=\u003cquery\u003e\u0026type=sites` - Export RSS feeds as OPML\n- `GET /api/export/csv?qry=\u003cquery\u003e\u0026type=sites` - Export RSS feeds as CSV\n\n## Search Syntax\n\n### Basic Search\n```\nai machine learning\n```\n\n### Site-specific Search\n```\nsite:openai.com\n```\n\n### Similar Posts/Blogs\n```\nlike:https://example.com/blog-post\nlike:example.com\n```\n\n### Content Type Filters\n- `type:blogs` - Blog posts only\n- `type:academic` - Academic papers\n- `type:news` - News articles\n- `type:feeds` - RSS feeds only\n\n### Time Filters\n- `since:last_week` - Past week\n- `since:last_month` - Past month\n- `since:last_year` - Past year\n\n## Project Structure\n\nThe codebase is organized into focused modules for maintainability:\n\n```\nblognerd.app/\n├── main.go           # Application bootstrap and routing (74 lines)\n├── types.go          # Data structures and type definitions\n├── handlers.go       # HTTP request handlers (home, search, API)\n├── search.go         # Search functionality and query processing\n├── rss.go            # RSS feed generation and caching\n├── export.go         # OPML and CSV export functionality\n├── custom_rss.go     # Custom RSS workflow processing\n├── utils.go          # Utility functions (parsing, formatting, etc.)\n├── pinecone.go       # Pinecone vector database client\n├── voyage.go         # Voyage AI embeddings client\n├── templates/        # HTML templates\n│   ├── index.html\n│   ├── head.html\n│   ├── styles.html\n│   ├── scripts.html\n│   ├── rss-builder.html\n│   ├── search-state.html\n│   ├── initial-state.html\n│   └── footer.html\n├── static/           # Static assets (CSS, images)\n├── .env.example      # Environment variables template\n├── Dockerfile        # Docker configuration\n├── go.mod           # Go module definition\n└── README.md        # This file\n```\n\n### Module Responsibilities\n\n- **`main.go`**: Minimal bootstrap code - initializes clients, templates, routes\n- **`types.go`**: All struct definitions (SearchResult, App, CustomRSSConfig, etc.)\n- **`handlers.go`**: HTTP handlers for web pages and API endpoints\n- **`search.go`**: Core search logic, Pinecone queries, result processing\n- **`rss.go`**: RSS feed generation with caching and cleanup\n- **`export.go`**: OPML and CSV export for RSS feeds\n- **`custom_rss.go`**: Advanced RSS workflow builder functionality\n- **`utils.go`**: Shared utilities for date parsing, URL cleaning, XML escaping\n- **`pinecone.go`**: Vector database client and operations\n- **`voyage.go`**: Embedding generation client\n\n## Development\n\n### Adding New Features\n\n1. **Backend changes**: Modify the appropriate Go files\n2. **Frontend changes**: Edit `templates/index.html`\n3. **Static assets**: Add to `static/` directory\n\n### Code Style\n\n- Follow standard Go conventions\n- Use `gofmt` for formatting\n- Add comments for public functions\n- Keep functions focused and small\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch: `git checkout -b feature-name`\n3. Make your changes and test thoroughly\n4. Commit with descriptive messages: `git commit -m \"Add feature description\"`\n5. Push to your fork: `git push origin feature-name`\n6. Create a pull request\n\n## License\n\nThis project is open source. See the repository for license details.\n\n## Support\n\nFor issues and questions:\n- Open an issue on GitHub\n- Check existing issues for similar problems\n\n## Acknowledgments\n\n- Powered by [Pinecone](https://pinecone.io/) vector database\n- Embeddings by [Voyage AI](https://www.voyageai.com/)\n- Built with [Go](https://golang.org/) and [Gorilla Mux](https://github.com/gorilla/mux)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falastairrushworth%2Fblognerd.app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falastairrushworth%2Fblognerd.app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falastairrushworth%2Fblognerd.app/lists"}