Most citation mistakes in essays and theses don't happen while writing the reference list. They happen weeks earlier, when you read a paper, copy a quote into your notes and forget the page number. Or you save the same article twice under slightly different titles.
Plagx Research Kit is a free, open-source notebook that fixes this at the source. You log each source as you read it, and Python turns the log into a correct APA 7 or MLA 9 reference list. It also checks the log for duplicates and missing details, and compares your draft's in-text citations against it.
π Open the notebook in Google Colab. Click Runtime β Run all. No setup is needed.
It also gives you templates to download: a source log, a literature matrix, an annotated bibliography and a research plan.
1. The source log
A source log is a spreadsheet with one row per source. These columns are the minimum you need to cite a source and find it again later:
| Column | Example |
|---|---|
id |
smith2020 |
type |
article-journal, book, chapter, webpage
|
authors |
Smith, John Allen; Lee, Kate |
year, title, container
|
Year, title, and journal/book/site name |
volume, issue, pages, doi, url
|
Whatever applies |
notes, quote, quote_page
|
Your summary, plus any exact quote with its page number |
Recording the page number next to every quote is the habit that saves the most time later.
2. From log row to citation
The notebook uses plagx-cite, an MIT-licensed Python package with no dependencies. It works with CSL-JSON, the format Zotero, Mendeley and Crossref export, so each log row is mapped to one CSL-JSON reference:
pip install plagx-cite
from plagx_cite import format_reference, cite_in_text
ref = {
"id": "smith2020",
"type": "article-journal",
"title": "Feedback timing and revision quality in undergraduate essays",
"author": [{"family": "Smith", "given": "John Allen"}, {"family": "Lee", "given": "Kate"}],
"issued": {"date-parts": [[2020]]},
"container-title": "Journal of Academic Writing",
"volume": "12", "issue": "3", "page": "45-67",
"DOI": "10.1234/jaw.2020.045",
}
print(format_reference(ref))
# Smith, J. A., & Lee, K. (2020). Feedback timing and revision quality in undergraduate essays.
# Journal of Academic Writing, 12(3), 45β67. https://doi.org/10.1234/jaw.2020.045
print(cite_in_text(ref, page="52")) # (Smith & Lee, 2020, p. 52)
print(cite_in_text(ref, narrative=True)) # Smith and Lee (2020)
print(cite_in_text(ref, style="mla", page="52")) # (Smith and Lee 52)
The example sources here and in the notebook are made up. The DOIs aren't real.
3. Check the log before you write
check_references finds duplicates (same DOI, or same title and first author) and missing details. In the notebook's example log, the same paper was saved twice: once with title-case capitalisation and a full https://doi.org/ link, and once without. Another source has no year:
from plagx_cite import check_references
report = check_references(refs)
for issue in report["issues"]:
print(issue["level"], issue["ref"], issue["message"])
# error smith2020b Possible duplicate (doi and title match) of smith2020: smith2020, smith2020b
# warning chen2021 No year (will show as n.d.)
The check runs locally and nothing is sent over the network. DOI lookups are optional and off by default.
4. Match the draft against the log
The most common reference-list mistake is a source cited in the text that never made it into the list, or the other way round. The notebook finds APA-style citations such as (Smith & Lee, 2020, p. 52) or Garcia (2018) with a regular expression and compares them with the log:
import re
CITATION = re.compile(r"([A-Z][\w'-]+)(?: (?:&|and) [A-Z][\w'-]+| et al\.)?,? \(?(\d{4})")
draft = """Early feedback changes how students revise (Smith & Lee, 2020, p. 52).
Garcia (2018) recommends paraphrasing from notes. Several studies support
peer review (Chen, 2021; Patel, 2019)."""
cited = {(name.lower(), year) for name, year in CITATION.findall(draft)}
logged = {("smith", "2020"), ("garcia", "2018"), ("chen", "2021"), ("okafor", "2022")}
print("Cited but not logged:", cited - logged) # {('patel', '2019')}
print("Logged but not cited:", logged - cited) # {('okafor', '2022')}
It's a simple pattern match and won't catch every citation format, but it catches the mistakes that cost marks.
5. Templates
The last cells write everything to an output folder and download it as a zip:
-
source_log_template.csv: a blank log with the columns above -
literature_matrix.csv: compare sources by method, findings, limitations and themes -
annotated_bibliography.md: formatted references with your notes under each -
research_plan.md: research question, scope, search strategy table and timeline -
references.json/references.bib: your sources as CSL-JSON and BibTeX, for Zotero, Mendeley or LaTeX
To use your own sources, upload your log (File β Save a copy in Drive first), and the same cells build your reference list and templates.
Links
- Colab notebook: plagx-research-kit
- Source (MIT): github.com/plagiarismcheckerx/plagx-research-kit-colab
- Citation package: plagx-cite on PyPI Β· npm Β· browser demo
By Plagiarism Checker X. This kit formats citations and checks your source log. It doesn't check for plagiarism or detect AI-generated text. For full plagiarism checks and AI-generated text detection, visit the Text Similarity Detector.
Top comments (0)