This guide explains how to contribute to and develop OpenSite Analytics.
opensource-site-tracking/
├── backend/ # FastAPI backend
│ ├── main.py # Main application
│ ├── models.py # SQLAlchemy models
│ ├── schemas.py # Pydantic schemas
│ ├── auth.py # Authentication logic
│ ├── config.py # Configuration
│ ├── database.py # Database connection
│ ├── utils.py # Utility functions
│ ├── tasks.py # Background tasks
│ ├── geoip.py # GeoIP service
│ ├── rate_limit.py # Rate limiting
│ ├── init_db.py # Database initialization
│ ├── requirements.txt # Python dependencies
│ └── .env # Environment variables
├── frontend/ # Next.js frontend
│ ├── src/
│ │ ├── app/ # Next.js app directory
│ │ │ ├── page.tsx # Dashboard
│ │ │ ├── login/ # Login page
│ │ │ ├── register/ # Registration page
│ │ │ └── site/ # Site analytics
│ │ ├── components/ # React components
│ │ │ └── ui/ # UI components
│ │ └── lib/ # Utilities
│ │ └── api.ts # API service
│ ├── package.json # Node dependencies
│ └── .env.local # Environment variables
└── docs/ # Documentation
Create a virtual environment:
:::bash
cd backend
python3 -m venv venv
source venv/bin/activate
Install development dependencies:
:::bash
pip3 install -r requirements.txt
pip3 install pytest pytest-asyncio httpx black flake8
Set up environment variables:
:::bash
cp .env.example .env
Initialize the database:
:::bash
python3 init_db.py
uvicorn main:app --host 0.0.0.0 --port 8000 --reload
Run tests with pytest:
pytest
Run specific test file:
pytest tests/test_auth.py
Format code with black:
black .
Check code quality with flake8:
flake8 .
Install dependencies:
:::bash
cd frontend
npm install
Set up environment variables:
:::bash
cp .env.example .env.local
npm run dev
npm run build
Run tests with jest:
npm test
Run tests in watch mode:
npm test -- --watch
Format code with prettier:
npm run format
Check code with ESLint:
npm run lint
Define the Pydantic schema in schemas.py:
:::python
class NewFeatureCreate(BaseModel):
name: str
value: str
class NewFeatureResponse(BaseModel):
id: int
name: str
value: str
created_at: datetime
Add the endpoint in main.py:
:::python
@app.post("/api/new-feature", response_model=NewFeatureResponse)
async def create_new_feature(
feature: NewFeatureCreate,
current_user: User = Depends(get_current_active_user),
db: Session = Depends(get_db)
):
# Your logic here
pass
Add the model to models.py if needed
Create a new page in src/app/:
:::bash
mkdir -p src/app/new-page
touch src/app/new-page/page.tsx
Add your page content:
:::tsx
'use client'
export default function NewPage() {
return (
Add navigation in the appropriate component
Create a new component in src/components/:
:::bash
touch src/components/NewComponent.tsx
Add your component:
:::tsx
interface NewComponentProps {
title: string
}
export default function NewComponent({ title }: NewComponentProps) {
return
Import and use it in your pages
For schema changes, you'll need to:
models.pyinit_db.pyExample migration script:
from database import SessionLocal, engine, Base
from models import YourModel
def migrate():
db = SessionLocal()
try:
# Your migration logic
db.commit()
finally:
db.close()
if __name__ == "__main__":
migrate()
API documentation is auto-generated using FastAPI's OpenAPI integration.
http://localhost:8000/docshttp://localhost:8000/redocUpdate docstrings in your endpoint functions to improve documentation:
@app.post("/api/endpoint")
async def endpoint_name(param: str):
"""
Endpoint description
Args:
param: Parameter description
Returns:
Response description
"""
pass
Real-time updates are implemented using WebSockets.
@app.websocket("/ws/{site_id}")
async def websocket_endpoint(websocket: WebSocket, site_id: int):
await manager.connect(websocket, site_id)
try:
while True:
data = await websocket.receive_text()
# Handle data
finally:
manager.disconnect(websocket, site_id)
class AnalyticsWebSocket {
constructor(siteId: number) {
this.siteId = siteId
this.ws = null
}
connect() {
this.ws = new WebSocket(`ws://localhost:8000/ws/${this.siteId}`)
this.ws.onmessage = (event) => {
const data = JSON.parse(event.data)
this.emit(data.type, data)
}
}
on(event: string, callback: Function) {
// Event handling
}
}
Create a feature branch:
:::bash
git checkout -b feature/your-feature-name
Make your changes
Commit your changes:
:::bash
git commit -m "Add your feature"
Push to your branch:
:::bash
git push origin feature/your-feature-name
Create a pull request
Tag the release:
:::bash
git tag -a v1.0.0 -m "Release version 1.0.0"
git push origin v1.0.0
Create GitHub release