citation-network-app
An interactive web app that fetches the top 20 related papers from Google Scholar (via SerpAPI), builds a citation graph, and renders it in pages of 10 nodes each.
Science Score: 44.0%
This score indicates how likely this project is to be science-related based on various indicators:
-
✓CITATION.cff file
Found CITATION.cff file -
✓codemeta.json file
Found codemeta.json file -
✓.zenodo.json file
Found .zenodo.json file -
○DOI references
-
○Academic publication links
-
○Committers with academic emails
-
○Institutional organization owner
-
○JOSS paper metadata
-
○Scientific vocabulary similarity
Low similarity (17.2%) to scientific vocabulary
Keywords
Repository
An interactive web app that fetches the top 20 related papers from Google Scholar (via SerpAPI), builds a citation graph, and renders it in pages of 10 nodes each.
Basic Info
Statistics
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
- Releases: 0
Topics
Metadata Files
README.md
Citation Network Visualization App
A professional-grade web application for visualizing citation networks of research papers using FastAPI, SerpAPI, NetworkX, and Matplotlib. This tool enables users to search scholarly topics and instantly see the network of related works based on Google Scholar data.
Table of Contents
- Overview
- Features
- Technology Stack
- Installation
- Usage Guide
- Project Structure
- Configuration
- Contributing
- License
Overview
This application allows users to:
- Enter a research paper title.
- Fetch and parse citation data using SerpAPI and Google Scholar.
- Visualize the resulting citation network in dynamic image format.
- Explore related papers and their citation counts.
The system automatically generates graph images for every 10 related papers to ensure clarity and usability.
Features
- Citation search via SerpAPI (Google Scholar engine).
- Dynamic citation network graph construction with NetworkX.
- Base64-encoded PNG visualizations rendered with Matplotlib.
- Clean, styled HTML interface using Jinja2 templates.
- Responsive, user-friendly design with HTML and CSS.
Technology Stack
- Backend Framework: FastAPI
- Search API: SerpAPI
- Graph Construction: NetworkX
- Graph Visualization: Matplotlib
- Frontend: HTML5, CSS3 (vanilla), Jinja2 templating
- Server: Uvicorn (ASGI)
Installation
Prerequisites
- Python 3.7+
- SerpAPI account and API key
Setup Instructions
```bash
Clone the repository
git clone https://github.com/
Create and activate a virtual environment
python3 -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
Install dependencies
pip install -r requirements.txt
Set your environment variable
echo "SERPAPIAPIKEY=yourkeyhere" > .env ```
Usage Guide
Run the application
bash
uvicorn main:app --reload
Access the interface
Open your browser and visit: http://127.0.0.1:8000
Search for a paper
- Enter a research paper title.
- Submit the form.
- View generated citation network graphs.
- Inspect citation counts and paper details.
Project Structure
citation-network-app/
├── main.py # Core FastAPI application
├── requirements.txt # Python dependencies
├── .env # API key (ignored in version control)
├── static/ # CSS files
│ └── style.css
├── templates/ # HTML templates
│ ├── index.html
│ └── results.html
├── .gitignore # Files/directories to ignore in git
├── LICENSE # License file (MIT)
├── README.md # Project documentation
└── Report.pdf # Supplementary project report
Configuration
- Create a
.envfile in the project root. - Add the following variable:
env
SERPAPI_API_KEY=your_actual_api_key
* You can also modify the number of papers retrieved or graph layout in main.py.
Contributing
We welcome contributions from the community. To contribute:
- Fork the repository.
- Create a new branch:
git checkout -b feature/your-feature - Make your changes and commit:
git commit -m "Add feature" - Push to your branch:
git push origin feature/your-feature - Open a pull request describing your changes.
Please follow consistent coding standards and ensure any added functionality is tested.
License
This project is licensed under the terms of the MIT License. See the LICENSE file for full details.
Owner
- Login: amr-yasser226
- Kind: user
- Repositories: 1
- Profile: https://github.com/amr-yasser226
Citation (citation-network-app/main.py)
from fastapi import FastAPI, Request, Form
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
from fastapi.responses import HTMLResponse
from serpapi import GoogleSearch
import networkx as nx
import matplotlib.pyplot as plt
import io
import base64
import uvicorn
app = FastAPI()
# Mount static files
app.mount("/static", StaticFiles(directory="static"), name="static")
# Setup Jinja2 templates
templates = Jinja2Templates(directory="templates")
def clean_title(raw_title):
while raw_title.startswith('['):
end_idx = raw_title.find(']')
raw_title = raw_title[end_idx + 1:].strip()
return raw_title
def extract_citation_info(search_results):
citations = []
for result in search_results["organic_results"]:
if "title" in result:
title = clean_title(result["title"])
citation_count = result.get("inline_links", {}).get("cited_by", {}).get("total", 0)
citations.append((title, citation_count))
return citations[:20]
def create_citation_graph(citations):
citation_graph = nx.Graph()
for title, count in citations:
citation_graph.add_node(title, citedby=count)
for idx, (title1, _) in enumerate(citations):
for title2, _ in citations[idx + 1:]:
citation_graph.add_edge(title1, title2)
return citation_graph
def generate_graph_image(citation_graph, start, stop):
subgraph = citation_graph.subgraph(list(citation_graph.nodes)[start:stop])
layout = nx.spring_layout(subgraph)
plt.figure(figsize=(20, 20))
node_sizes = [subgraph.nodes[n].get('citedby', 1) * 10 for n in subgraph.nodes]
nx.draw(subgraph, layout, with_labels=True, labels={n: n for n in subgraph.nodes},
node_size=node_sizes, node_color="lightblue", font_size=8)
plt.title(f"Papers {start + 1} to {stop} Citation Network")
buffer = io.BytesIO()
plt.savefig(buffer, format='png')
buffer.seek(0)
plt.close()
return base64.b64encode(buffer.getvalue()).decode('utf-8')
@app.get("/", response_class=HTMLResponse)
async def homepage(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
@app.post("/search")
async def perform_search(request: Request, paper_title: str = Form(...)):
api_key = 'a68bd84b1c4c552050b39561d28ec9cbe4eefd14ebb7af554955afdaa3861b7c'
search_query = GoogleSearch({
"engine": "google_scholar",
"q": paper_title,
"api_key": api_key,
"num": 20
})
search_results = search_query.get_dict()
citation_info = extract_citation_info(search_results)
citation_graph = create_citation_graph(citation_info)
graph_images = []
for i in range(0, len(citation_info), 10):
end = min(i + 10, len(citation_info))
graph_image = generate_graph_image(citation_graph, i, end)
graph_images.append({
"image": graph_image,
"papers": citation_info[i:end]
})
return templates.TemplateResponse("results.html", {
"request": request,
"graphs": graph_images
})
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
GitHub Events
Total
- Watch event: 1
- Push event: 5
- Create event: 2
Last Year
- Watch event: 1
- Push event: 5
- Create event: 2
Issues and Pull Requests
Last synced: 6 months ago
Dependencies
- Jinja2 ==3.1.6
- MarkupSafe ==3.0.2
- PyYAML ==6.0.2
- annotated-types ==0.7.0
- anyio ==4.9.0
- certifi ==2025.6.15
- charset-normalizer ==3.4.2
- click ==8.2.1
- contourpy ==1.3.2
- cycler ==0.12.1
- fastapi ==0.115.13
- fonttools ==4.58.4
- h11 ==0.16.0
- httptools ==0.6.4
- idna ==3.10
- kiwisolver ==1.4.8
- matplotlib ==3.10.3
- networkx ==3.5
- numpy ==2.3.0
- packaging ==25.0
- pillow ==11.2.1
- pydantic ==2.11.7
- pydantic_core ==2.33.2
- pyparsing ==3.2.3
- python-dateutil ==2.9.0.post0
- python-dotenv ==1.1.0
- requests ==2.32.4
- serpapi ==0.1.5
- six ==1.17.0
- sniffio ==1.3.1
- starlette ==0.46.2
- typing-inspection ==0.4.1
- typing_extensions ==4.14.0
- urllib3 ==2.5.0
- uvicorn ==0.34.3
- uvloop ==0.21.0
- watchfiles ==1.1.0
- websockets ==15.0.1