A full-stack application for creating and managing text snippets with AI-generated summaries. Built with Ruby on Rails (backend) and Next.js (frontend).
- Create Snippets: Paste text content and automatically generate AI-powered summaries
- View Snippets: Browse all your saved snippets with their summaries
- AI Integration: Supports both OpenAI and Google Gemini for summary generation
- RESTful API: Clean, well-documented API endpoints
- Modern UI: Beautiful, responsive interface built with Next.js
- Docker and Docker Compose
- (Optional) Ruby 3.3+ and Node.js 22+ for local development
-
Clone the repository
git clone <repository-url> cd Pluga
-
Configure environment variables
Create a
.envfile in the root directory:# AI Provider Configuration # Options: 'openai' or 'gemini' AI_PROVIDER=openai # OpenAI Configuration (if using OpenAI) OPENAI_API_KEY=your_openai_api_key_here # Gemini Configuration (if using Gemini) GEMINI_API_KEY=your_gemini_api_key_here
-
Get your AI API Key
For OpenAI:
- Visit OpenAI API Keys
- Create a new API key
- Copy the key and add it to your
.envfile asOPENAI_API_KEY
For Gemini:
- Visit Google AI Studio
- Create a new API key
- Copy the key and add it to your
.envfile asGEMINI_API_KEY
-
Start the application
docker compose up
This will:
- Start PostgreSQL database
- Start Rails API on port 3000
- Start Next.js frontend on port 4000
- Run database migrations automatically
-
Access the application
- Frontend: http://localhost:4000
- Backend API: http://localhost:3000
-
Install dependencies
cd backend bundle install -
Setup database
# Make sure PostgreSQL is running bundle exec rails db:create bundle exec rails db:migrate
-
Configure environment
cp .env.example .env # Edit .env with your API keys -
Run the server
bundle exec rails server
-
Install dependencies
cd frontend npm install -
Configure environment
cp .env.example .env.local # Edit .env.local if needed (defaults to http://localhost:3000) -
Run the development server
npm run dev
cd backend
bundle exec rspeccd frontend
npm testBackend:
cd backend
bundle exec rubocopFrontend:
cd frontend
npm run lintPOST /snippets
Content-Type: application/json
{
"text": "Your text content here..."
}
# Response (201 Created)
{
"id": 1,
"text": "Your text content here...",
"summary": "AI-generated summary..."
}GET /snippets/:id
# Response (200 OK)
{
"id": 1,
"text": "Your text content here...",
"summary": "AI-generated summary..."
}GET /snippets
# Response (200 OK)
[
{
"id": 1,
"text": "First snippet text...",
"summary": "First summary..."
},
{
"id": 2,
"text": "Second snippet text...",
"summary": "Second summary..."
}
]Using curl:
# Create a snippet
curl -X POST http://localhost:3000/snippets \
-H "Content-Type: application/json" \
-d '{
"text": "Ruby on Rails is a web application framework written in Ruby. It follows the Model-View-Controller (MVC) architectural pattern and emphasizes convention over configuration."
}'
# Get all snippets
curl http://localhost:3000/snippets
# Get a specific snippet
curl http://localhost:3000/snippets/1Pluga/
├── backend/ # Rails API
│ ├── app/
│ │ ├── controllers/ # API controllers
│ │ ├── models/ # ActiveRecord models
│ │ └── services/ # Business logic (AI service)
│ ├── config/ # Rails configuration
│ ├── db/ # Database migrations
│ ├── spec/ # RSpec tests
│ └── Dockerfile
├── frontend/ # Next.js application
│ ├── app/ # Next.js app directory
│ ├── __tests__/ # Jest tests
│ └── Dockerfile
├── docker-compose.yml # Docker orchestration
└── README.md
Backend:
AI_PROVIDER: AI provider to use (openaiorgemini)OPENAI_API_KEY: OpenAI API key (required if using OpenAI)GEMINI_API_KEY: Gemini API key (required if using Gemini)DATABASE_USER: PostgreSQL username (default:postgres)DATABASE_PASSWORD: PostgreSQL password (default:postgres)DATABASE_HOST: PostgreSQL host (default:dbfor Docker)
Frontend:
NEXT_PUBLIC_API_URL: Backend API URL (default:http://localhost:3000)
The project includes a GitHub Actions workflow (.github/workflows/ci.yml) that:
- Runs Rubocop linting on the backend
- Runs RSpec tests on the backend
- Runs ESLint on the frontend
- Runs Jest tests on the frontend
-
Error Handling & User Experience
- Add more granular error messages for different failure scenarios
- Implement retry logic for AI API calls
- Add loading states and progress indicators for long-running operations
- Implement optimistic UI updates
-
Testing
- Add integration tests for the full stack
- Increase test coverage, especially edge cases
- Add E2E tests with Playwright or Cypress
- Mock AI responses more comprehensively in tests
-
Performance & Scalability
- Implement caching for frequently accessed snippets
- Add pagination for the snippets list endpoint
- Implement background jobs (Sidekiq) for AI summary generation to avoid blocking requests
- Add database indexes for better query performance
-
Features
- Add snippet editing and deletion
- Implement search and filtering
- Add user authentication and multi-user support
- Allow users to regenerate summaries with different parameters
- Add export functionality (CSV, JSON)
-
Security
- Add rate limiting to prevent API abuse
- Implement input sanitization and validation
- Add CORS configuration for production
- Implement API authentication/authorization
-
DevOps
- Add health check endpoints
- Implement proper logging and monitoring
- Add staging environment configuration
- Set up automated deployments
-
Synchronous AI Calls: I chose to generate summaries synchronously during snippet creation. This simplifies the implementation but could lead to slow responses if the AI API is slow. In production, I would use background jobs.
-
Simple UI: The frontend is intentionally simple and focused on core functionality. I prioritized working features over advanced UI components, which could be enhanced with a component library like Material-UI or Tailwind CSS.
-
Single Database: Using a single PostgreSQL database for simplicity. For a production system handling high volume, I might consider read replicas or separate databases for different concerns.
-
No Authentication: Skipped user authentication to focus on core functionality. This is a necessary feature for a production system but adds complexity that wasn't required for the challenge.
-
Basic Error Handling: Implemented basic error handling that covers the main scenarios. More sophisticated error handling with retries, circuit breakers, and detailed logging would be needed for production.
-
Docker Development Focus: The Docker setup is optimized for development. Production deployments would need multi-stage builds, smaller images, and better security practices.
This project was created as part of the Pluga technical challenge.