diff --git a/development/about/index.html b/development/about/index.html index 0afc442..dbcf0c4 100644 --- a/development/about/index.html +++ b/development/about/index.html @@ -649,11 +649,12 @@
Kerko was inspired by prior work accomplished by Whisky Echo Bravo on two projects:
Since then, Kerko has continued to evolve, thanks to work by Whisky Echo Bravo and other contributors, often through funding provided diff --git a/development/config-params/index.html b/development/config-params/index.html index 6ec2a75..3be9e3c 100644 --- a/development/config-params/index.html +++ b/development/config-params/index.html @@ -3877,7 +3877,7 @@
weight
kerko.meta.
¶google_analytics_id
¶A Google Analytics stream ID, e.g., 'G-??????????'
.
A Google Analytics measurement ID, e.g., 'G-??????????'
.
If the value is not empty and Flask is not running in debug mode, then the Google Analytics tag is inserted into the pages.
Type: String
diff --git a/development/deploying/index.html b/development/deploying/index.html
index d55da6b..152c623 100644
--- a/development/deploying/index.html
+++ b/development/deploying/index.html
@@ -465,9 +465,9 @@
These instructions will detail the steps and configurations required to get -KerkoApp running on an Ubuntu 20.04 or 22.04 web server, using Gunicorn as +KerkoApp running on an Ubuntu 22.04 or 24.04 web server, using Gunicorn as the WSGI container and nginx as a HTTP proxy.
The procedure is similar that of any Flask application, but KerkoApp-specific steps are also covered here.
diff --git a/development/index.html b/development/index.html index 7ba5507..69ef47b 100644 --- a/development/index.html +++ b/development/index.html @@ -760,10 +760,13 @@Kerko is a web application component that provides a user-friendly search and browsing interface for sharing a bibliography managed with the Zotero reference manager.
The combination of Kerko and Zotero gives you the best of both worlds: a rich but easy to use web interface for end-users of the bibliography, and a well-established and powerful bibliographic reference management tool for individuals or teams working on the bibliography's content.
"},{"location":"#how-it-works","title":"How it works","text":"A Kerko-powered bibliography is managed using Zotero, and stored in the cloud on zotero.org, while Kerko itself is incorporated into an application which is installed on a web server. The bibliographic references may reside in a Zotero group library, where multiple users may collaborate to manage the content, or in a Zotero private library. On the web server, Kerko maintains a search index, which is a copy of the Zotero library that is optimized for search. When users interact with the web application, Kerko gets all the required data from that search index, without ever contacting zotero.org. It is through a scheduled task, which runs at regular intervals, that Kerko automatically brings its search index up to date by using the Zotero Web API to retrieve the latest data from zotero.org.
Kerko is implemented in Python using the Flask framework. As an application component, Kerko only works when incorporated into a Flask application. Such an application, KerkoApp, is available for you to use, and can be deployed on a web server. KerkoApp can be seen as just a thin layer over Kerko. It might work for you if you like the default appearance, and if the provided configuration options are sufficient for your needs.
For more advanced needs, you could consider building a custom application, possibly derived from KerkoApp, where additional customizations could be implemented in Python. In this scenario, it is not recommended that you change Kerko itself, but that you use Kerko's Python API to implement your customizations. Kerko is actually a Flask \"blueprint\" (similar to what some other systems might call a plugin or an extension), which allows a modular architecture where the application integrates and extends Kerko, and possibly other blueprints as well; the Kerko-powered bibliography could be just one component of a larger Flask application.
"},{"location":"#demo-site","title":"Demo site","text":"A demo site, which is based on KerkoApp, is available for you to try. You may also view the Zotero library that contains the source data for the demo site.
"},{"location":"#sites-using-kerko","title":"Sites using Kerko","text":"The following sites are powered by Kerko:
Are you using Kerko?
If you would like to add your Kerko-powered site to this list, please e-mail us or submit a pull request.
"},{"location":"#features","title":"Features","text":"The main features provided by Kerko are:
AND
: matches items that contain all specified terms. This is the default relation between terms when no operator is specified, e.g., a b
is the same as a AND b
.OR
: matches items that contain any of the specified terms, e.g., a OR b
.NOT
: excludes items that match the term, e.g., NOT a
.(a OR b) AND c
.\"a b c\"
. The default difference between word positions is 1, meaning that an item will match if it contains the words next to each other, but a different maximum distance may be selected (with the tilde character), e.g. \"web search\"~2
allows up to 1 word between web
and search
, meaning it could match web site search
as well as web search
.faceted^2 search browsing^0.5
specifies that faceted
is twice as important as search
when computing the relevance score of results, while browsing
is half as important. Boosting may be applied to a logical grouping, e.g., (a b)^3 c
.search
, searches
, and searching
all return the same results. The Snowball algorithm is used for that purpose.KerkoApp is a standalone application built around Kerko. It inherits all of Kerko's features and it provides a few additions of its own:
Kerko requires Python 3.8 or later.
Required Python packages will be automatically installed when installing Kerko. The main ones are:
The following front-end resources are loaded from CDNs by Kerko's default templates (but could be completely removed or replaced in custom templates):
Before choosing Kerko for your project, you might want to review the following known limitations of Kerko:
Kerko was inspired by prior work accomplished by Whisky Echo Bravo on two projects:
In 2019, Whisky Echo Bravo was asked to work on another similar project. That made it clear that a general solution would benefit many organizations. However, software from the prior projects had to be rewritten in order to be more adaptable to a variety of needs. That led to Kerko, whose initial development was made possible through the following project:
Since then, Kerko has continued to evolve, thanks to work by Whisky Echo Bravo and other contributors, often through funding provided by organizations needing new features or customizations of Kerko.
"},{"location":"about/#design-choices","title":"Design choices","text":"Here are some of the design choices that have guided the development of Kerko so far:
The name Zotero reportedly derives from the Albanian word zot\u00ebroj, which means \"to learn something extremely well, that is to master or acquire a skill in learning\" (Source: Mark Dingemanse, 2008, Etymology of Zotero).
The name Kerko is a nod to Zotero as it takes a similar etymological route: it derives from the Albanian word k\u00ebrkoj, which means \"to ask, to request, to seek, to look for, to demand, to search\" and seems fit to describe a search tool.
"},{"location":"changelog/","title":"Changelog","text":"Before doing an upgrade, please check the \"How to upgrade\" section of the Kerko documentation.
"},{"location":"changelog/#120-2024-08-03","title":"1.2.0 (2024-08-03)","text":"New features:
kerko.facets.language.enabled
configuration parameter to true
. By default, Kerko will try to normalize the language names to make the facet more usable; see kerko.facets.language.
in the configuration parameters documentation for details.Removed features:
setup.py
have been removed. Equivalent pybabel
commands can be used instead (see the updated Localization section of the documentation).Other changes:
kerko.facets.item_type.initial_limit
, now 10
instead of 0
.kerko.facets.item_type.initial_limit_leeway
, now 4
instead of 2
.kerko.facets.link.initial_limit_leeway
, now 0
instead of 2
.kerko.facets.tag.initial_limit
, now 10
instead of 0
.kerko.facets.tag.initial_limit_leeway
, now 4
instead of 2
.kerko.facets.year.initial_limit_leeway
, now 0
instead of 2
.setup.cfg
to pyproject.toml
.pip
do not mistake a development version for a previously published version. Version numbers are now extracted from the tags and revisions of the Git repository.Deprecated APIs:
kerko.TRANSLATION_DIRECTORIES
is deprecated and will be removed in Kerko 2.x. The variable kerko.TRANSLATION_DIRECTORY
should be used instead, and its type is a string instead of a list. If you are using a custom application, please adapt it accordingly (you may check KerkoApp's __init__.py
for an example).Features:
kerko.scopes.pubyear.enabled
configuration parameter to false
.kerko.pages.*.
for defining content pages whose content come from selected Zotero standalone notes.\"page\"
type for the kerko.link_groups.*.
configuration table, to allow the creation of links to content pages.kerko.performance.whoosh_index_memory_limit
and kerko.performance.whoosh_index_processors
to give some control over the Whoosh search engine's indexing performance.Bug fixes:
caseName
search field.kerko.features.print_results_max_count
is greater than zero.Other changes:
rel=\"noopener\"
to target=\"_blank\"
links.rel=\"noreferrer\"
to links derived from Zotero library data, e.g., user-provided URLs, DOIs, link attachments.kerko.performance.whoosh_index_memory_limit
parameter.page-len=1
URL parameter. This is achieved through removal of the id
parameter from pagination URLs. Obtaining those ids was requiring extra processing. Instead, the id
parameter is now added through the browser History API when a pagination link is visited.Backwards incompatible changes:
Possibly backwards incompatible changes (more or less internal API changes):
kerko.blueprint
global object. Applications must now instantiate the blueprint by calling kerko.make_blueprint()
before registering it. This prevents attempts to mutate the object after its registration, especially in tests.kerko.extractors.TransformerExtractor
no longer applies transformers on None
values. If you need a transformer to process a None
value (Kerko itself has no such transformer), you now have to set the new skip_none_value
argument to False
when instantiating the extractor.Features:
kerko.features.download_item
.Bug fixes:
errno.EINTR
error code). Not an issue anyone should have encountered!Backwards incompatible changes:
kerko.features.download_results_link
\u2192 kerko.features.download_results
.kerko.features.print_item_link
\u2192 kerko.features.print_item
kerko.features.print_results_link
\u2192 kerko.features.print_results
Other changes:
Features:
kerko.link_groups.*.
for defining sets of links that may be used for navigation.kerko.breadcrumb
and kerko.link_groups.breadcrumb_base
).Bug fixes:
kerko.zotero.csl_style
configuration parameter.Backwards incompatible changes:
kerko.link_groups.navbar
configuration. There is no default translation for it. To change the default text or to translate it, you must override the default kerko.link_groups.navbar
in your configuration file. If you have overridden the _navbar_items.html.jinja2
template and wish to use the configuration, you might want to adapt it, or revert to the default template.Other changes:
Features:
--full
option to the sync
command line interface (CLI) command.Bug fixes:
kerko.facets.*.collection_key
configuration parameter.kerko.features.download_results_max_count
and kerko.features.print_results_max_count
configuration parameters.Other changes:
Rename the default branch of the repository from 'master' to 'main'. If you have cloned the repository with Git, use the following commands to rename your local branch:
git branch -m master main\ngit fetch origin\ngit branch -u origin/main main\ngit remote set-head origin -a\n
Make the config
CLI command show the configuration in TOML format.
config
CLI command hide secrets by default. Add a --show-secrets
option.Backwards incompatible changes:
clean
CLI command from cleaning everything by default. To delete everything, you now have to run flask kerko clean everything
. This may help prevent accidental deletion of the cache, which in some instances can take long to rebuild.kerko.citation_formats.*
\u2192 kerko.bib_formats.*
.kerko.features.download_citations_link
\u2192 kerko.features.download_results_link
kerko.features.download_citations_max_count
\u2192 kerko.features.download_results_max_count
kerko.features.print_citations_link
\u2192 kerko.features.print_results_link
kerko.features.print_citations_max_count
\u2192 kerko.features.print_results_max_count
item_citation_download
\u2192 item_bib_download
search_citation_download
\u2192 search_bib_download
Warning: Upgrading from version 0.9 or earlier will require that you adapt your installation and configuration files, then rebuild your search index. Use the commands below, then restart the application. If you are using KerkoApp, make sure to check its changelog.
flask kerko clean index\nflask kerko sync index\n
Features:
kerko.features.open_in_zotero_app
and kerko.features.open_in_zotero_web
). Even when these are enabled, a user who wishes to use such button must first enable it from the (also new) Preferences dialog.kerko config
command to the Flask command line interface for displaying all configuration parameters.Other changes:
Backwards incompatible changes:
DATA_PATH
and INSTANCE_PATH
configuration parameters. You may need to set one or both of those parameters, and/or move your existing data directory.kerko.config_helpers.config_set()
function. Here is a mapping of the changed parameters:KERKO_BOOTSTRAP_VERSION
\u2192 kerko.assets.bootstrap_version
KERKO_CSL_STYLE
\u2192 kerko.zotero.csl_style
KERKO_COMPOSER
\u2192 kerko_composer
KERKO_DATA_DIR
\u2192 DATA_PATH
. Now optional, relative to the instance path, and defaulting to kerko
instead of data/kerko
.KERKO_DOWNLOAD_ATTACHMENT_NEW_WINDOW
\u2192 kerko.features.download_attachment_new_window
KERKO_DOWNLOAD_CITATIONS_LINK
\u2192 kerko.features.download_citations_link
KERKO_DOWNLOAD_CITATIONS_MAX_COUNT
\u2192 kerko.features.download_citations_max_count
KERKO_FEEDS
\u2192 kerko.feeds.formats
KERKO_FEEDS_FIELDS
\u2192 kerko.feeds.fields
KERKO_FEEDS_MAX_DAYS
\u2192 kerko.feeds.max_days
KERKO_FEEDS_REJECT_ANY
\u2192 kerko.feeds.reject_any
KERKO_FEEDS_REQUIRE_ANY
\u2192 kerko.feeds.require_any
KERKO_FULLTEXT_SEARCH
\u2192 kerko.search.fulltext
KERKO_HIGHWIREPRESS_TAGS
\u2192 kerko.meta.highwirepress_tags
KERKO_JQUERY_VERSION
\u2192 kerko.assets.jquery_version
KERKO_PAGE_LEN
\u2192 kerko.pagination.page_len
KERKO_PAGER_LINKS
\u2192 kerko.pagination.pager_links
KERKO_POPPER_VERSION
\u2192 kerko.assets.popper_version
KERKO_PRINT_CITATIONS_LINK
\u2192 kerko.features.print_citations_link
KERKO_PRINT_CITATIONS_MAX_COUNT
\u2192 kerko.features.print_citations_max_count
KERKO_PRINT_ITEM_LINK
\u2192 kerko.features.print_item_link
KERKO_RELATIONS_INITIAL_LIMIT
\u2192 kerko.features.relations_initial_limit
KERKO_RELATIONS_LINKS
\u2192 kerko.features.relations_links
KERKO_RELATIONS_SORT
\u2192 kerko.features.relations_sort
KERKO_RESULTS_ABSTRACTS_MAX_LENGTH
\u2192 kerko.features.results_abstracts_max_length
KERKO_RESULTS_ABSTRACTS_MAX_LENGTH_LEEWAY
\u2192 kerko.features.results_abstracts_max_length_leeway
KERKO_RESULTS_ABSTRACTS
\u2192 kerko.features.results_abstracts
KERKO_RESULTS_ABSTRACTS_TOGGLER
\u2192 kerko.features.results_abstracts_toggler
KERKO_RESULTS_ATTACHMENT_LINKS
\u2192 kerko.features.results_attachment_links
KERKO_RESULTS_FIELDS
\u2192 kerko.search.result_fields
KERKO_RESULTS_URL_LINKS
\u2192 kerko.features.results_url_links
KERKO_TEMPLATE_ATOM_FEED
\u2192 kerko.templates.atom_feed
KERKO_TEMPLATE_BASE
\u2192 kerko.templates.base
KERKO_TEMPLATE_ITEM
\u2192 kerko.templates.item
KERKO_TEMPLATE_LAYOUT
\u2192 kerko.templates.layout
KERKO_TEMPLATE_SEARCH
\u2192 kerko.templates.search
KERKO_TEMPLATE_SEARCH_ITEM
\u2192 kerko.templates.search_item
KERKO_TITLE
\u2192 kerko.meta.title
KERKO_WHOOSH_LANGUAGE
\u2192 kerko.search.whoosh_language
KERKO_WITH_JQUERY
\u2192 kerko.assets.with_jquery
KERKO_WITH_POPPER
\u2192 kerko.assets.with_popper
KERKO_ZOTERO_API_KEY
\u2192 ZOTERO_API_KEY
KERKO_ZOTERO_BATCH_SIZE
\u2192 kerko.zotero.batch_size
KERKO_ZOTERO_LIBRARY_ID
\u2192 ZOTERO_LIBRARY_ID
KERKO_ZOTERO_LIBRARY_TYPE
\u2192 ZOTERO_LIBRARY_TYPE
KERKO_ZOTERO_LOCALE
\u2192 kerko.zotero.locale
KERKO_ZOTERO_MAX_ATTEMPTS
\u2192 kerko.zotero.max_attempts
KERKO_ZOTERO_WAIT
\u2192 kerko.zotero.wait
kerko.config_helpers.config_update(app.config, kerko.DEFAULTS)
.Composer.__init__()
now only takes a configuration object as argument instead of a bunch of arguments. Thus, the initial values of the Composer
instance now depend solely on the configuration.KERKO_USE_TRANSLATIONS
configuration variable. Kerko now relies on the application's default Babel domain and translation directories. Custom applications that wish to load Kerko's translations should now add kerko.TRANSLATION_DOMAIN
and kerko.TRANSLATION_DIRECTORIES
to their Babel configuration.__init__()
method of FacetSpec
and its subclasses now only accept keyword arguments.sort_key
argument to FacetSpec.__init__()
is now sort_by
.Composer
built-in fields z_dateAdded
and z_dateModified
are now named date_added
and date_modified
respectively.Warning: Upgrading from version 0.8.x or earlier will require that you rebuild your search index. Use the following commands, then restart the application:
flask kerko clean index\nflask kerko sync index\n
Features:
kerko count
CLI command (mostly meant for development purposes).Bug fixes:
KERKO_PRINT_CITATIONS_LINK
and KERKO_DOWNLOAD_CITATIONS_LINK
are both set to False
.kerko sync
CLI command not returning an error code with some types of failures.Other changes:
page
parameter from pagination links when page=1
.pyproject.toml
.Backwards incompatible changes:
KERKO_FACET_COLLAPSING
option. The new initial limit on facets values made this feature largely redundant.collapsible
param from the FacetSpec
class.KERKO_ZOTERO_START
and KERKO_ZOTERO_END
(were only used for development and no longer practical).Changes that might break custom themes:
facet
, facet_item
, facet_items
, facet_fields
template macros have changed.facets-container
, facets
, and facets-modal-body
element ids are now required in search.html.jinja2
.Possibly backwards incompatible changes (more or less internal API changes):
criteria
module. Criteria.keywords
and Criteria.filters
work pretty much as before, but everything else has changed.query
module, which had organically grown into an tangled mess, now replaced with the searcher
module. This new API is completely different.searcher
API.views
module into multiple modules under views
(item_creators
, item_facets
, item_relations
, routes
, search
), and moved breadbox
, meta
(as item_meta
), pager
, and sorter
under views
.Bug fixes:
Warning: Upgrading from version 0.7.x or earlier will require that you clean and re-sync your existing search index. Use the following commands, then restart the application:
flask kerko clean index\nflask kerko sync\n
Features:
KERKO_FULLTEXT_SEARCH
to False
. Since this feature relies on Zotero's full-text indexing, you must make sure that it works in Zotero first; see Zotero's documentation.KERKO_RESULTS_URL_LINKS
to False
.KERKO_RESULTS_ATTACHMENT_LINKS
to False
.standalone_attachment_download
, lets one retrieve a standalone file attachment.KERKO_RESULTS_ABSTRACTS_MAX_LENGTH
and KERKO_RESULTS_ABSTRACTS_MAX_LENGTH_LEEWAY
).KERKO_HIGHWIREPRESS_TAGS
to False
.href
attribute of <a>
elements.Bug fixes:
Other changes:
sync cache
command to the command line interface.sortable
Whoosh flag on relevant fields._
) are now trimmed from facet value labels. This happens after sorting the values, which means that the underscore can still be used as a prefix to alter the alphabetical order.type
HTML attribute to record download links.rel=\"alternate\"
HTML attribute to record download links on item pages. Also add a corresponding link
element to the page head
.Backwards incompatible changes:
kerko index
CLI command (use kerko sync
instead).Possibly backwards incompatible changes (more or less internal API changes):
KERKO_RESULTS_FIELDS
setting now includes the 'url'
field. If you have overridden that setting in your application and KERKO_RESULTS_URL_LINKS
is enabled, you'll probably have to add 'url'
too.item_type
has been renamed to item_type_label
. If you have custom templates, please review any use of item.item_type
.kerko/_search-result.html.jinja2
template has changed somewhat. If you have overridden it, you'll need to review the changes.ItemContext
class has been eliminated. The Extractor.extract()
method now receives an item's dictionary instead of an ItemContext
object, and if an item has children these are now available directly in the item (with the children
key). If you have created custom extractor classes, their extract()
method will need to be adapted accordingly.BaseAttachmentsExtractor
\u2192 BaseChildAttachmentsExtractor
BaseNotesExtractor
\u2192 BaseChildNotesExtractor
LinkedURIAttachmentsExtractor
\u2192 ChildLinkedURIAttachmentsExtractor
NotesTextExtractor
\u2192 ChildNotesTextExtractor
RawNotesExtractor
\u2192 RawChildNotesExtractor
RelationsInNotesExtractor
\u2192 RelationsInChildNotesExtractor
StoredFileAttachmentsExtractor
\u2192 ChildFileAttachmentsExtractor
item_attachment_download
\u2192 child_attachment_download
alternateId
\u2192 alternate_id
Security fixes:
Bug fixes:
Other changes:
Documentation changes:
Warning: Upgrading from version 0.6 or earlier will require that you clean and re-sync your existing search index. Use the following commands, then restart the application:
flask kerko clean index\nflask kerko sync\n
Features:
_cites
tag.dc.replaces
relation that's managed internally by Zotero on some operations such as item merges.id
parameter to the search result URLs, and redirect the user to that item's permanent URL if the search result no longer matches because of database changes.search
to the search form.aria-label
attribute to many elements.aria-current
attribute to indicate the current value of widgets.Bug fixes:
Other changes:
setup.py
to setup.cfg
.src
layout.Backwards incompatible changes:
pager
dict passed to the _pager.html.jinja2
template are now lists. Previously, only the values at keys 'before'
and 'after'
were lists; now the values at keys 'previous'
, 'first'
, 'current'
, 'last'
, and 'next'
are lists as well.'blacklist'
and 'whitelist'
in variable names are replaced with 'exclude'
and 'include'
.KERKO_RESULTS_ABSTRACT
configuration variable is replaced by two variables, KERKO_RESULTS_ABSTRACTS
(note the now plural form) and KERKO_RESULTS_ABSTRACTS_TOGGLER
.{url_prefix}/{itemID}/export/{format}
for individual items ('export'
has been inserted), and {url_prefix}/export/{format}/
for search result pages ('download'
has been replaced by 'export'
).Extractor
class' interface has changed, improving consistency and separation of concerns:__init__()
must now be specified as keyword arguments.extract()
method no longer have a document
argument, and the spec
argument is now the last one. The method now returns a value instead of assigning it to the document.extract_and_store()
method handles extraction, encoding, and assignment to the document, assigning the value only when it is not None
.AttachmentsExtractor
class has been renamed to StoredFileAttachmentsExtractor
.InCollectionExtractor
now extends collection membership to subcollections. To preserve the previous behavior, set the check_subcollections
parameter to False
when initializing the extractor.Possibly backwards incompatible changes (more or less internal API changes):
search_results
variable passed to the search.html.jinja2
template is now an iterator of tuples, where the first element of each tuple is a result, and the second element the URL of the result.Security fixes:
Backwards incompatible changes:
KERKO_DATA_DIR
configuration variable. KerkoApp users don't need to worry about this as KerkoApp takes care of it, but custom apps that did not already set this variable now have to.Features:
KERKO_DOWNLOAD_ATTACHMENT_NEW_WINDOW
configuration variable to control whether to open documents in a new window or in the same window.Bug fixes:
Other changes:
Possibly backwards incompatible changes (more or less internal API changes):
content_with_badges
template macro as badges
, and leave it to the caller to display content.Warning: Upgrading from version 0.4 or earlier will require that you clean and re-sync your existing search index. Use the following commands:
flask kerko clean index\nflask kerko sync\n
Features:
KERKO_TEMPLATE_*
configuration variables for page template names.renderer
argument to kerko.specs.FacetSpec
, kerko.specs.BadgeSpec
).KERKO_RESULTS_FIELDS
configuration variable to specify which fields to retrieve with search queries.kerko.extractors.InCollectionExtractor
, new parameters for kerko.codecs.BooleanFacetCodec
).Bug fixes:
Other changes:
kerko index
in favor of new command kerko sync
.Possibly backwards incompatible changes (more or less internal API changes):
kerko.composer.Composer.__init__()
.kerko.composer.Composer.__init__()
arguments default_note_whitelist_re
as default_child_whitelist_re
, default_note_blacklist_re
as default_child_blacklist_re
.kerko.views.item()
as kerko.views.item_view()
._facet.html.jinja2
as _facets.html.jinja2
.checkboxes
in template macro field()
with add_link_icon
and remove_link_icon
.Features:
faceted^2 search browsing^0.5
.Security fixes:
Other changes:
AndNot
, AndMaybe
, Require
were unwanted but enabled by default by Whoosh's OperatorsPlugin
).Features:
Bug fixes:
Other changes:
Possibly backwards incompatible changes (more or less internal API changes):
kerko.composer.Composer.get_ordered_specs()
replaces get_ordered_scopes()
, get_ordered_facets()
and get_ordered_sorts()
.In this section, we will assume that you are using Kerko through KerkoApp. Some elements may not apply if you have integrated Kerko into your own custom Flask application (see Configuration in custom applications).
"},{"location":"config-basics/#parameter-styles","title":"Parameter styles","text":"When looking at Kerko configuration options, you will quickly notice two styles of parameter names, uppercase names and lowercase names.
Uppercase names, such as SECRET_KEY
, ZOTERO_LIBRARY_ID
, DATA_PATH
, BABEL_DEFAULT_LOCALE
, follow the usual convention for environment variables. Most Flask and Flask extensions parameter names follow this convention. Some Kerko parameters have uppercase names too, but only those parameters that may usefully be set as environment variables. Internally, those parameters are stored into a flat Python dictionary.
Most of Kerko parameters use lowercase names. They are also organized into a hierarchy, and are usually referenced using dot-separated paths. Examples are: kerko.features.results_abstracts
, kerko.meta.title
, kerko.facets.item_type.enabled
. Internally, those parameters are stored into nested Python dictionaries.
Documentation convention
In this manual, we will generally refer to a hierarchical parameter using its full dot-separated path, for example kerko.meta.title
, except when context makes repeating the full path redundant.
KerkoApp provides two ways to set configuration parameters:
The above list is in ascending order of precedence. This means that a given parameter set in a TOML file can be overridden by an environment variable.
We do not recommend configuring the same parameter in multiple places, as that might confuse systems administrators, but a layered approach is useful in implementing the Twelve-factor App methodology.
TOML files are the preferred and most convenient way of configuring KerkoApp. Environment variables, however, are still supported, as some parameters cannot be set in TOML files, such as FLASK_APP
and KERKOAPP_CONFIG_FILES
.
The TOML syntax allows organizing parameters under headers to avoid repetition and to make the file more readable. Therefore, two following two examples are equivalent ways of setting the kerko.meta.title
parameter:
kerko.meta.title = \"My Awesome Bibliography\"\n
TOML example 2[kerko.meta]\ntitle = \"My Awesome Bibliography\"\n
Note that if headers are used in a TOML file, any top-level parameter must be set above the first header:
Correct TOML exampleZOTERO_LIBRARY_ID = \"123456\"\n\n[kerko.meta]\ntitle = \"My Awesome Bibliography\"\n
Incorrect TOML example[kerko.meta]\ntitle = \"My Awesome Bibliography\"\n\nZOTERO_LIBRARY_ID = \"123456\"\n
By default, KerkoApp will look for a series of TOML files:
config.toml
instance.toml
.secrets.toml
For each of those, KerkoApp first looks for the file into the current working directory. If it does not find it there, it searches by traversing directories upwards until it finds the file or reaches the root directory. At this point, if the file is still not found, the same scanning process is reapplied, but this time starting from the instance path. After that, whether the file was found or not, KerkoApp continues with the next filename in the list.
The files are loaded in the specified order. The parameters from each file get merged into the previously known configuration. If a given parameter was already set, its value is overwritten by the one from the later file.
This approach allows a layered configuration where:
config.toml
contains general (public) parameters. It is safe (and wise) to manage this file in a code repository.instance.toml
contains server-specific parameters such as those that might refer to paths or systems that only exist on the server. This file is usually not put into a code repository..secrets.toml
contains secrets (private parameters) that ought to be known only to the server, such as API keys. This file should never be added to a code repository.You do not have to use all three files. One might, for example, use just config.toml
and .secrets.toml
, and not create instance.toml
.
You may replace the default list of TOML file paths by setting the KERKOAPP_CONFIG_FILES
environment variable.
In the example below, the default list of TOML files is replaced by a list of two file paths, one relative and the other absolute:
POSIXWindowsKERKOAPP_CONFIG_FILES=\"first_config.toml;/absolute/path/to/second_config.toml\"\n
KERKOAPP_CONFIG_FILES=\"first_config.toml;C:\\absolute\\path\\to\\second_config.toml\"\n
"},{"location":"config-basics/#environment-variables","title":"Environment variables","text":"KerkoApp requires environment variable names to be prefixed with KERKOAPP_
. The SECRET_KEY
parameter, for example, becomes KERKOAPP_SECRET_KEY
when specified as an environment variable.
For hierarchical parameters, each dot separator (.
) must be replaced by two underscore characters (__
). The kerko.meta.title
parameter, for example, becomes KERKOAPP_kerko__meta__title
when specified as an environment variable. Such conversion is not necessary in TOML files.
Note that Windows does not allow lowercase environment variable names. Consequently, Windows users have no choice but to set lowercase parameters in TOML files.
Environment variables may be set from various locations, in the following order (refer to the Flask documentation for more details):
.flaskenv
file..env
file.--env-file
command line option.The above list is in ascending order of precedence. This means that a given parameter set earlier can be overridden later as values get loaded. Files are located by scanning directories upwards from the directory you call flask from.
"},{"location":"config-basics/#configuration-in-custom-applications","title":"Configuration in custom applications","text":"If you are using a custom Flask application instead of KerkoApp, some of the present documentation may not fully apply to you. For example:
KERKOAPP_
, or no prefix at all.In a custom application, hierarchical parameters may be set in Python using the API provided by Kerko, as in the following example:
Setting a configuration parameter in Pythonfrom kerko.config_helpers import config_set\nconfig_set(app.config, \"kerko.meta.title\", \"My Awesome Bibliography\")\n
Such assignments must be done during the initialization process. The application cannot change a setting while responding to a request.
"},{"location":"config-basics/#viewing-the-configuration","title":"Viewing the configuration","text":"With configuration parameters potentially taking values from different sources (default values, configuration files, environment variables), you may sometimes want to verify the actual values taken by each parameter.
The following command will show the configuration parameters of the application and their values:
flask kerko config\n
"},{"location":"config-guides/","title":"Configuration guides","text":"This sections provides guidance on configuring specific aspects of Kerko.
"},{"location":"config-guides/#defining-custom-facets-based-on-zotero-collections","title":"Defining custom facets based on Zotero collections","text":"Zotero collections can be mapped to custom facets in Kerko. With this scheme, a collection in the Zotero library represents a facet, and its subcollections correspond to values (or user-selectable filters) within the facet. Figure 1 below illustrates such mapping, taken from the demo library and its corresponding demo site.
Figure 1. Side-by-side comparison between the structure of collections in a Zotero library and the resulting faceted browsing interface in Kerko.For such mapping to work, the following conditions must be met:
Once your Zotero library it set up to meet those conditions, you may configure the facets. For the example in Figure 1, the configuration looks like this:
[kerko.facets.topic]\nenabled = true\ntype = \"collection\"\ncollection_key = \"KY3BNA6T\"\nfilter_key = \"topic\"\ntitle = \"Topic\"\nweight = 110\ninitial_limit = 5\ninitial_limit_leeway = 2\n\n[kerko.facets.field_of_study]\nenabled = true\ntype = \"collection\"\ncollection_key = \"7H2Q7L6I\"\nfilter_key = \"field-of-study\"\ntitle = \"Field of study\"\nweight = 120\ninitial_limit = 5\ninitial_limit_leeway = 2\n\n[kerko.facets.contribution]\nenabled = true\ntype = \"collection\"\ncollection_key = \"JFQRH4X2\"\nfilter_key = \"contribution\"\ntitle = \"Contribution\"\nweight = 130\ninitial_limit = 5\ninitial_limit_leeway = 2\n
For details on each parameter, please refer to the parameters documentation. However, we can highlight some elements:
collection_key
is the key assigned by Zotero to identify the collection. An easy way to find this key is to visit your library using Zotero's web interface. Click the collection, and check its URL in your browser's address bar. In our example, the URL of the \"Topic\" collection is https://www.zotero.org/groups/2348869/kerko_demo/collections/KY3BNA6T, hence the use of \"KY3BNA6T\"
as the collection key.filter_key
tells Kerko the key to use in URLs when a user of your Kerko site selects a filter within the facet. In our example, for the \"Topic\" facet we chose to set this parameter to \"topic\"
and, consequently, the search URL will look like https://demo.kerko.whiskyechobravo.com/bibliography/?topic=Z8LT6QZG.2ZGZH2E2.title
is the heading that Kerko will show for the facet. If desired, you may choose a title that is different from the collection's name in Zotero.weight
determines the relative position of the facet. Small numbers (low weights) rise above large ones (heavier weights). This explains why, in our example, Kerko displays \"Topic\" (weighting 110) above \"Field of study\" (120) and \"Contribution\" (130).Other things to know:
After adding a new facet, you must clean and re-sync the search index. Please check the documentation on synchronization, but in short you have to use the following commands:
flask kerko clean index\nflask kerko sync index\n
Kerko allows a facet to have any number of hierarchical sublevels (nested subcollections).
Phew! We think that this is simpler to setup in practice than it looks in writing. Hopefully you will agree.
"},{"location":"config-guides/#creating-custom-content-pages-based-on-zotero-standalone-notes","title":"Creating custom content pages based on Zotero standalone notes","text":"If you wish to provide informational pages along with your bibliography, you can add standalone notes to your Zotero library, and configure Kerko to provide pages whose content will come from those notes.
Say you want to provide \"About\" and \"Contact Us\" pages with simple text content, you could implement them by following these steps:
\"Y48RBWDB\"
is the item ID.Define the \"About\" and \"Contact Us\" pages by adding the following snippet to your Kerko configuration:
[kerko.pages.about]\npath = \"/about\"\nitem_id = \"Y48RBWDB\"\ntitle = \"About\"\n\n[kerko.pages.contact_us]\npath = \"/contact\"\nitem_id = \"REG3CL25\"\ntitle = \"Contact Us\"\n
... where:
path
is the desired URL path for the page;item_id
is the note's item ID (as found earlier);title
is the desired title for the page in the Kerko site.For more details on each parameter, please refer to the parameters documentation.
Then, you will probably want the navigation bar to provide links to your pages. The following configuration code defines a navigation bar with three links \u2014 a link to the bibliography, and links to the \"About\" and \"Contact Us\" pages:
[[kerko.link_groups.navbar]]\ntype = \"endpoint\"\nendpoint = \"kerko.search\"\ntext = \"Bibliography\"\n\n[[kerko.link_groups.navbar]]\ntype = \"page\"\npage = \"about\"\ntext = \"About\"\n\n[[kerko.link_groups.navbar]]\ntype = \"page\"\npage = \"contact_us\"\ntext = \"Contact Us\"\n
... where:
type
parameter indicates the type of link (\"endpoint\"
indicates a core Kerko link, while \"page\"
indicates a link to a page defined under kerko.pages.*
);page
parameter specifies the target of the link, e.g., the unique key of the page (which replaces the *
in the kerko.pages.*
header);text
parameter provides the link's text to show in the navigation bar.Navigation bar links will be displayed in the order they appear in the configuration file.
For more details on this configuration section, please refer to the parameters documentation
Make sure Kerko's database is up-to-date with your new note by running the following command:
flask kerko sync\n
Restart your Kerko application to load the configuration changes. If all goes well, you will have new \"About\" and \"Contact Us\" pages accessible from the navigation bar.
Please note that Kerko does not restructure the HTML that Zotero generates for notes. If you use headings in your notes, we recommend that you start with the \"Heading 2\" heading level, because \"Heading 1\" should be reserved to Kerko (for the page title).
Kerko is not, and never will be, a web content management system. Its sole purpose is to provide a nice interface for a Zotero library. Thus, Kerko content pages are just a very rudimentary way of providing simple informational content along with the library. For more advanced content needs, you might have to consider integrating Kerko into a custom Flask application backed with proper content editing features.
"},{"location":"config-guides/#ensuring-full-text-indexing-of-your-attachments-in-zotero","title":"Ensuring full-text indexing of your attachments in Zotero","text":"Kerko's full-text indexing relies on text content extracted from attachments by Zotero. Consequently, for Kerko's full-text search to work, you must make sure that full-text indexing works in Zotero first; see Zotero's documentation on full-text indexing.
Individual attachments in Zotero can be indexed, partially indexed, or unindexed. Various conditions may cause an attachment to be partially indexed or unindexed, e.g., file is large, has not been processed yet, or does not contain text.
Zotero shows the indexing status in the attachment's right pane. If it shows \"Indexed: Yes\", all is good. If it shows \"Indexed: No\" or \"Indexed: Partial\", then clicking the \"Reindex Item\" button (next to the indexing status) should ensure that the attachment gets fully indexed, that is if the file actually contains text. If there is no \"Reindex Item\" button, it probably means that Zotero does not support that file type for full-text indexing (at the moment, it only supports PDF and plain text files).
It can be tedious to go through hundreds of attachments just to find out whether they are indexed or not. To make things easier, you could create a saved search in your Zotero library to get an always up-to-date list of unindexed PDFs. Use the following search conditions:
This search might return a long list of unindexed attachments. To reindex them all at once, you may select them, then right-click to get the contextual menu, and select \"Reindex items\". It may require some time to update your library on zotero.org. Note that documents that have no text content, as well as missing documents, will still be considered as unindexed and appear in the results of the saved search.
Controlling the indexing status will not only improve full-text search on your Kerko site, but also full-text search from within Zotero!
"},{"location":"config-guides/#providing-cites-and-cited-by-relations","title":"Providing Cites and Cited by relations","text":"Zotero allows one to link items together through its Related field. However, such relations are not typed nor directed, making it impossible (1) to indicate the nature of the relation, or (2) to distinguish which of two related items is the citing entity, and which is the one being cited. Consequently, Kerko has its own method for setting up those relations.
To establish Cites relations in your Zotero library, you must follow the procedure below:
https://www.zotero.org/groups/9999999/items/ABCDEFGH
or https://www.zotero.org/users/9999999/items/ABCDEFGH
._cites
. That tag that will tell Kerko that this particular note is special, that it contains relations.At the next synchronization, Kerko will retrieve the references found in notes tagged with _cites
. Afterwards, proper hyperlinked citations will appear in the Cites and Cited by sections of the related bibliographic records.
Remarks:
zotero://select/
) in the notes, if you prefer those to Zotero URIs.href
attribute of <a>
elements.This section describes most configuration parameters available to Kerko and KerkoApp.
Unless indicated otherwise, all parameters are optional and will take a default value if omitted from your configuration.
Note
Flask and Flask extensions loaded by the application may provide additional configuration parameters that are not described in this manual. To find those, please refer to the documentation of the relevant package.
Changing the Kerko configuration can be disruptive
Making any change to a Kerko configuration file requires that you at least restart the application afterwards for the change to become effective.
Moreover, some parameters have an effect on the structure of the cache or the search index that Kerko depends on. Changing this kind of parameter may require that you rebuild either. Refer to the documentation of the parameter to check if specific actions need to be taken after a change.
Prefix your environment variables
KerkoApp users must prefix parameter names with KERKOAPP_
when configuring them as environment variables. However, that prefix should be omitted when the same parameter is set in a TOML file. See environment variables for details.
Be a minimalist, only set a parameter when necessary
If a parameter's default value works for you, just omit that parameter from your configuration file. Your configuration file will be much smaller and easier to read, and you will have less things to check when eventually upgrading Kerko.
"},{"location":"config-params/#babel_default_locale","title":"BABEL_DEFAULT_LOCALE
","text":"The default language of the user interface.
Type: String Default value: \"en\"
BABEL_DEFAULT_TIMEZONE
","text":"The timezone to use for user facing times. Any timezone name supported by the pytz package should work.
Type: String Default value: \"UTC\"
CONFIG_FILES
","text":"Specifies where to look for one or more TOML configuration files. The value must be a semicolon-separated list of file paths.
The files are loaded in the specified order. The parameters from each file get merged into the previously known configuration. If a given parameter was already set, its value is overwritten by the one from the later file.
Paths may be absolute or relative. Relative paths are resolved from the current working directory. If a specified file is not found there, it is searched by traversing the directories upwards. If the root directory is reached and the file is still not found, then the same search method is reapplied, but this time starting from the INSTANCE_PATH
.
Type: String Default value: \"config.toml;instance.toml;.secrets.toml\"
Environment variable only
This parameter is specific to KerkoApp and cannot be set in a TOML file. It can only be set as an environment variable, therefore it should actually be referenced as KERKOAPP_CONFIG_FILES
. See environment variables for details.
DATA_PATH
","text":"The data path specifies a directory where Kerko may store its cache, search index, and file attachments. This may be provided as an absolute path or as a relative path. If a relative path is given, it will be relative to INSTANCE_PATH
.
Type: String Default value: \"kerko\"
INSTANCE_PATH
","text":"The instance path specifies a directory where the application may store data and configuration files.
Type: String Default value: Determined by Flask. In practice, the default for KerkoApp users is a directory named instance
located at the same level as the wsgi.py
file. You may set INSTANCE_PATH
to a different directory, which you must specify as an absolute path.
Environment variable only
This parameter is specific to KerkoApp and cannot be set in a TOML file. It can only be set as an environment variable, therefore it should actually be referenced as KERKOAPP_INSTANCE_PATH
. See environment variables for details.
LOGGING_ADDRESS
","text":"Address to send log messages to. Used only if LOGGING_HANDLER
is set to \"syslog\"
.
Type: String Default value: \"/dev/log\"
LOGGING_FORMAT
","text":"Log message format string, with %-style placeholders. Refer to the Python logging documentation for allowed attributes.
Type: String Default value: \"[%(asctime)s] %(levelname)s in %(module)s: %(message)s\"
LOGGING_HANDLER
","text":"Logging handler to use. At this time, the sole allowed value is \"syslog\"
. If no value is set, the default handler will write to the default stream (usually sys.stderr
).
Type: String
"},{"location":"config-params/#logging_level","title":"LOGGING_LEVEL
","text":"Severity of events to log. Allowed values are \"DEBUG\"
, \"INFO\"
, \"WARNING\"
, \"ERROR\"
, and \"CRITICAL\"
.
Type: String Default value: \"DEBUG\"
if the application is running in debug mode, or \"WARNING\"
otherwise.
SECRET_KEY
","text":"This parameter is required for generating secure tokens in web forms. It should have a hard to guess value, and should really remain secret.
This parameter is required and has no default value.
Type: String
"},{"location":"config-params/#zotero_api_key","title":"ZOTERO_API_KEY
","text":"This parameter specifies your Zotero API key, as created on zotero.org.
Kerko does not need to write to your library. Thus, we recommend that your API key be read-only, and that it does not grant any more access to your Zotero data than strictly necessary.
On zotero.org, the API key creation options vary on whether you want to connect Kerko to a personal library or to a group library:
Personal libraryGroup libraryMake sure to check Allow library access, as well as Allow notes access, unless you are certain you won't need any Kerko feature that relies on notes. If you are unsure at this point, we recommend that you allow notes access, otherwise some features might not work, and when that happens you might not remember that it is the API key that is blocking notes access. You can always edit the API key later.
We recommend that you use Per group permissions so that access is strictly restricted to the chosen group. Make sure that Read Only is selected for that group. This will grant read-only access to all items of that group, including notes.
This parameter is required and has no default value.
Type: String
"},{"location":"config-params/#zotero_library_id","title":"ZOTERO_LIBRARY_ID
","text":"The identifier of the Zotero library to get data from.
Finding your library ID:
Personal libraryGroup libraryFor a personal library, the value is your userID, as found on zotero.org (you must be logged-in).
For a group library this value is the groupID of the library, as found in the URL of the library (e.g., the groupID of the library at https://www.zotero.org/groups/2348869/kerko_demo
is \"2348869\"
).
This parameter is required and has no default value.
Type: String
"},{"location":"config-params/#zotero_library_type","title":"ZOTERO_LIBRARY_TYPE
","text":"The type of library to get data from, either \"user\"
for a personal library, or \"group\"
for a group library.
This parameter is required and has no default value.
Type: String
"},{"location":"config-params/#kerkobib_formats","title":"kerko.bib_formats.*.
","text":"Bibliographic record download formats, where *
is a format key.
The default formats are:
bibtex
ris
The configuration system does not allow adding new formats.
"},{"location":"config-params/#enabled","title":"enabled
","text":"Enable the format. If this is set to false
, the format will not be available through any download link.
Type: Boolean
Modifies the cache and the search index
Changing this parameter from false
to true
will require that you run the sync cache --full
and sync index
commands. See synchronization commands for details.
extension
","text":"File extension of the downloadable file.
Type: String
"},{"location":"config-params/#help_text","title":"help_text
","text":"Description of the format, to show in the help window.
Type: String
"},{"location":"config-params/#label","title":"label
","text":"Label to use in the format selector.
Type: String
"},{"location":"config-params/#mime_type","title":"mime_type
","text":"MIME type of the downloadable format.
Type: String
"},{"location":"config-params/#weight","title":"weight
","text":"Relative position of the format in lists. Formats with low weights (small numbers) rise above heavier ones (large numbers).
Type: Integer
"},{"location":"config-params/#kerkobreadcrumb","title":"kerko.breadcrumb.
","text":"A breadcrumb is a navigational aid that displays the location of the current page in relation to the structure of a website.
If enabled, the breadcrumb works in relation with the kerko.link_groups.breadcrumb_base
parameter, which defines the base (starting links) of the breadcrumb trail, which Kerko dynamically completes with one or more links based on the current location within Kerko.
enabled
","text":"Enable the breadcrumb.
Type: Boolean Default value: true
include_current
","text":"Include the current page at the end of the breadcrumb trail. If set to false
, the breadcrumb trail will end with the parent page instead of the current page.
Type: Boolean Default value: true
text_max_length
","text":"Maximum length for a breadcrumb item's text (in number of characters). If text is to be truncated in the middle of a word, the whole word is discarded instead. Truncated text is appended with an ellipsis sign (\"...\").
If set to 0
, no truncation will be applied.
Type: Integer Default value: 50
text_max_length_leeway
","text":"If the length of a breadcrumb item's text only exceeds kerko.breadcrumb.text_max_length
by this tolerance margin or less (in number of characters), the text will not be truncated.
This parameter has no effect if text_max_length
is set to 0
(no truncation).
Type: Integer Default value: 10
kerko.facets.*.
","text":"Facets to provide in the search interface, where *
is a facet key. The facet key is used internally by Kerko to identify the facet.
The default facets are:
item_type
(item types facet, enabled by default)language
(item languages facet, disabled by default)link
(items with links facet, disabled by default)tag
(item tags facet, enabled by default)year
(item years facet, enabled by default)You may define additional facets. See Defining custom facets based on Zotero collections.
Modifies the search index
Most of the kerko.facets.*
parameters require that you run the clean index
and sync index
commands after you have changed them. See synchronization commands for details.
collection_key
","text":"Key of the Zotero collection to map the facet to. This must refer to a top-level collection containing at least one hierarchical level of subcollections. Each subcollection will be mapped to a filter under the facet, if it contains at least one item that is not excluded through the kerko.zotero.item_include_re
or kerko.zotero.item_exclude_re
parameters.
This parameter has no default value and is required for facets whose type
parameter is set to \"collection\"
.
Type: String
"},{"location":"config-params/#enabled_2","title":"enabled
","text":"Enable the facet.
Type: Boolean Default value: depends on which facet you are looking at.
"},{"location":"config-params/#filter_key","title":"filter_key
","text":"Key to use in URLs when filtering with the facet.
Type: String Default value: depends on which facet you are looking at.
"},{"location":"config-params/#initial_limit","title":"initial_limit
","text":"Maximum number of filters to show by default under the facet. Excess filters will be shown if the user clicks a \"view more\" button. A value of 0
means no limit.
Type: Integer Default value: depends on which facet you are looking at.
"},{"location":"config-params/#initial_limit_leeway","title":"initial_limit_leeway
","text":"If the number of filters under the facet exceeds initial_limit
by this tolerance margin or less, all filters will be shown. A value of 0
means no tolerance margin.
Type: Integer Default value: depends on which facet you are looking at.
"},{"location":"config-params/#item_view","title":"item_view
","text":"Show the facet on item view pages.
Type: Boolean Default value: depends on which facet you are looking at.
"},{"location":"config-params/#sort_by","title":"sort_by
","text":"List of criteria used for sorting the filters under the facet. Allowed values in this list are \"count\"
and \"label\"
.
Type: Array of strings Default value: depends on which facet you are looking at.
"},{"location":"config-params/#sort_reverse","title":"sort_reverse
","text":"Reverse the sort order of the filters under the facet.
Type: Boolean Default value: depends on which facet you are looking at.
"},{"location":"config-params/#title","title":"title
","text":"Heading of the facet.
Type: String Default value: depends on which facet you are looking at.
"},{"location":"config-params/#type","title":"type
","text":"Type of facet. Determines the data source of the facet.
Allowed values are:
\"collection\"
: Use a Zotero collection as source.\"item_type\"
: Use the item type as source.\"language\"
: Use item Language field as source.\"link\"
: Use item URL field as source.\"tag\"
: Use Zotero tags as source.\"year\"
: Use the item year field as source.This parameter is required and has no default value.
Type: String
"},{"location":"config-params/#weight_1","title":"weight
","text":"Relative position of the facet in lists. Facets with low weights (small numbers) rise above heavier ones (large numbers).
Type: Integer Default value: depends on which facet you are looking at.
"},{"location":"config-params/#kerkofacetslanguage","title":"kerko.facets.language.
","text":"The parameters in this section only apply to the language
facet.
Source values for the language facet are extracted from the Language field of Zotero items.
"},{"location":"config-params/#allow_invalid","title":"allow_invalid
","text":"Allow values that are not found in the pycountry language database.
This parameter has an effect only if normalize
is set to true
.
If this parameter is set to true
, non-standard or badly entered language names will be allowed to appear in the language facet. You may find that you have to clean your data in Zotero if you wish to make the facet usable.
If this parameter is set to false
, non-standard or badly entered language names will be omitted from the language facet. The facet will only show recognized languages but may give an incomplete picture of all the languages present in your library.
Type: Boolean Default value: true
locale
","text":"The locale to use when displaying language names in the language facet. Translations are provided by pycountry.
This parameter has an effect only if normalize
is set to true
.
Type: String Default value: \"en\"
normalize
","text":"Normalize language names using the pycountry language database.
If this parameter is set to true
, slight inconsistencies in your data can be attenuated, preventing unwanted duplicates in the facet. For example, values such as fr
, FR
, fra
, Fra
, fre
, fr-FR
, fr-fr
, fr-CA
, or French
will all fall under a single French
term in the facet. The normalization process is case insensitive, ignores country or area codes, and recognizes:
Terms not falling into any of the above categories will be considered invalid. To choose what to do with invalid terms, see the allow_invalid
parameter.
For the best results with the normalize
option, we recommend that you record languages in Zotero using 2-letter ISO 639-1 codes (because they also happen to be supported by the Citation Style Language), or 3-letter ISO 639-3 codes for languages not covered by ISO 639-1.
If normalize
is set to false
, item language values will be used verbatim. In that case, the facet will work equally well if your language data is well controlled and consistent. This is the way to go if languages are consistently recorded using their non-English names in your Zotero library.
Type: Boolean Default value: true
values_separator_re
","text":"Regular expression to use for splitting the content of Zotero's Language field into multiple languages, e.g., en; de; it
. We do not necessarily recommend recording multiple languages in the Language field, but in practice some people do when describing multilingual resources.
Type: String Default value: \";\"
kerko.features.
","text":""},{"location":"config-params/#download_attachment_new_window","title":"download_attachment_new_window
","text":"Open attachments in new tabs. In other words: add the HTML target=\"_blank\"
attribute to attachment links.
Type: Boolean Default value: false
download_item
","text":"Provide a record download button on item pages.
To configure the bibliographic formats made available for downloading, see kerko.bib_formats
.
Type: Boolean Default value: true
download_results
","text":"Provide a record download button on search results pages.
To configure the bibliographic formats made available for downloading, see kerko.bib_formats
.
Type: Boolean Default value: true
download_results_max_count
","text":"Limit over which the record download button should be hidden from search results pages.
Type: Integer Default value: 0
(i.e., no limit)
open_in_zotero_app
","text":"On item pages, show a button for opening the corresponding item in the Zotero application (through a link using the zotero://
protocol). If this parameter is set to true
, a user will still need to first enable the button from the Preferences menu (which can be accessed from the footer of item pages and saves the user's choices in browser cookies). For the link to work, the user must also have the Zotero application installed, and have access to the Zotero library. This feature is generally only useful to library editors and might confuse other users, especially if your Zotero library is private. Thus you should probably enable this option only if there is a strong need from the editors.
Type: Boolean Default value: false
open_in_zotero_web
","text":"On item pages, show a button for viewing the corresponding item on zotero.org (through a regular hyperlink). If this parameter is set to true
, a user will still need to first enable the button from the Preferences menu (which can be accessed from the footer of item pages and saves the user's choices in browser cookies). For the link to work, the user must also have access to the Zotero library. This feature is generally only useful to library editors and might confuse other users, especially if your Zotero library is private. Thus you should probably enable this option only if there is a strong need from the editors.
Type: Boolean Default value: false
print_item
","text":"Provide a print button on item pages.
Type: Boolean Default value: false
print_results
","text":"Provide a print button on search results pages.
Type: Boolean Default value: false
print_results_max_count
","text":"Limit over which the print button should be hidden from search results pages.
Type: Integer Default value: 0
(i.e., no limit)
relations_initial_limit
","text":"Number of related items to show above the \"show more\" link.
Type: Integer Default value: 5
relations_links
","text":"Show item links in lists of related items.
Enabling this only has an effect if at least one of the following variables is also set to true
: kerko.features.results_attachment_links
, kerko.features.results_url_links
.
Type: Boolean Default value: false
results_abstracts
","text":"Show abstracts on search result pages.
Type: Boolean Default value: false
(i.e., hide abstracts)
results_abstracts_toggler
","text":"Show a button letting users show or hide abstracts on search results pages.
Type: Boolean Defaults value: true
(i.e., toggle is displayed)
results_abstracts_max_length
","text":"Truncate abstracts at the given length (in number of characters). If text is to be truncated in the middle of a word, the whole word is discarded instead. Truncated text is appended with an ellipsis sign (\"...\").
Type: Integer Default value: 0
(i.e., abstracts get displayed in their full length, without any truncation)
results_abstracts_max_length_leeway
","text":"If the length of an abstract only exceeds kerko.features.results_abstracts_max_length
by this tolerance margin or less (in number of characters), it will not be truncated.
This parameter has no effect if results_abstracts_max_length
is set to 0
(no truncation).
Type: Integer Default value: 0
(i.e., no tolerance margin).
results_attachment_links
","text":"Provide links to attachments in search results.
Type: Boolean Default value: true
results_url_links
","text":"Provide links to online resources in search results (for items whose URL field has a value).
Type: Boolean Default value: true
kerko.feeds.
","text":""},{"location":"config-params/#formats","title":"formats
","text":"A list of syndication feed formats to publish.
If set to an empty array, no web feed will be provided. The only supported format at this time is 'atom'
.
Type: Array of strings Default value: [\"atom\"]
fields
","text":"List of fields to retrieve for each feed item. Values in this list are keys identifying fields defined in the kerko_composer
object, and the list must contain all fields that are used by the kerko.templates.atom_feed
template.
One probably only needs to change the default list when overriding the template to display additional fields.
Note that some fields from the default list may be required by Kerko, and removing those could cause crashes.
Type: Dictionary
"},{"location":"config-params/#max_days","title":"max_days
","text":"The age (in number of days) of the oldest items allowed into web feeds. The date field of the items is used for that purpose, and when no date is available, the date the item was added to Zotero is used instead.
Unless your goal is to promote recent literature only, you should probably keep the default value.
Items with missing dates will be considered as very recent, to prevent them from being excluded from feeds. For the same reason, items whose date lack the month and/or the day will be considered as from the 12th month of the year and/or the last day of the month.
Type: Integer Default value: 0
(i.e., no age limit)
kerko.link_groups.*.
","text":"Link groups, where *
is an arbitrary key used for identifying the group. Each group is a list which must contain at least one link defined using one or more of the sub-parameters described below.
Link groups can be used for navigation or anywhere hyperlinks are needed. Templates can use the key to retrieve a desired link group.
Kerko provides default navbar
and breadcrumb_base
link groups. In TOML format, these are defined as below (the double brackets indicate a list item):
[[kerko.link_groups.navbar]]\ntype = \"endpoint\"\nendpoint = \"kerko.search\"\ntext = \"Bibliography\"\n\n[[kerko.link_groups.breadcrumb_base]]\ntype = \"endpoint\"\nendpoint = \"kerko.search\"\ntext = \"Bibliography\"\n
"},{"location":"config-params/#anchor","title":"anchor
","text":"Anchor to append to the endpoint's URL.
This optional parameter is only allowed when the type
parameter is set to \"endpoint\"
.
Type: String
"},{"location":"config-params/#endpoint","title":"endpoint
","text":"Name of the endpoint within the application to use as target for the link. Use this for internal links. For example, the endpoint for the Kerko search page is \"kerko.search\"
.
This parameter is required if the type
parameter is set to \"endpoint\"
and has no default value.
Type: String
"},{"location":"config-params/#external","title":"external
","text":"Generate a full URL (with scheme and domain) for the endpoint instead of an internal URL.
This parameter is only allowed when the type
parameter is set to \"endpoint\"
.
Type: Boolean Default value: false
new_window
","text":"Open the link in a new tab.
Type: Boolean Default value: false
page
","text":"Key of the page to use as target for the link. That page must have been defined in kerko.pages.*
.
This parameter is required if the type
parameter is set to \"page\"
(and cannot be used with other type
values).
Type: String
"},{"location":"config-params/#parameters","title":"parameters
","text":"Dictionary of parameters to pass to the endpoint. Unknown keys are appended to the URL as query string arguments, like ?a=b&c=d
.
This optional parameter is only allowed when the type
parameter is set to \"endpoint\"
.
Type: Dictionary
"},{"location":"config-params/#scheme","title":"scheme
","text":"Protocol to use in the endpoint's URL.
This parameter is only allowed when the type
parameter is set to \"endpoint\"
and the external
parameter is set to true
.
Type: String Default value: Same protocol as the current request
"},{"location":"config-params/#text","title":"text
","text":"Text to use for the link.
This parameter is required and has no default value.
Type: String
"},{"location":"config-params/#type_1","title":"type
","text":"Type of link being configured. Other parameters may or may not be available depending on this value.
Allowed values are:
\"endpoint\"
: Link to an application page (served by a Flask endpoint).\"page\"
: Link to a page defined in kerko.pages.*
.\"url\"
: Link to an arbitrary URL.This parameter is required and has no default value.
Type: String
"},{"location":"config-params/#url","title":"url
","text":"URL of the external link.
This parameter is required if the type
parameter is set to \"url\"
.
Type: String
"},{"location":"config-params/#weight_2","title":"weight
","text":"Relative position of the link in lists. Links with low weights (small numbers) rise above heavier ones (large numbers). At equal weights, links are ordered based on their order of appearance in the configuration.
Type: Integer Default value: 0
kerko.meta.
","text":""},{"location":"config-params/#google_analytics_id","title":"google_analytics_id
","text":"A Google Analytics stream ID, e.g., 'G-??????????'
.
If the value is not empty and Flask is not running in debug mode, then the Google Analytics tag is inserted into the pages.
Type: String Default value: \"\"
highwirepress_tags
","text":"Embed Highwire Press tags into the HTML of item pages. This should help search engines such as Google Scholar index your items more accurately, but works only with book, conference paper, journal article, report or thesis items.
Type: Boolean Default value: true
(i.e., enabled).
title
","text":"The title to display in web pages.
Type: String
"},{"location":"config-params/#kerkopages","title":"kerko.pages.*.
","text":"Simple content pages, where *
is an arbitrary key you must choose to uniquely identify the page. The content of the page will come from a Zotero standalone note of your choosing.
The key can be used in kerko.link_groups.*
tables to define hyperlinks to the page.
path
","text":"The path to use in the URL of the page. Must start with a slash (/
) character.
Type: String
"},{"location":"config-params/#item_id","title":"item_id
","text":"The Zotero item ID of the note to use as content for the page.
Type: String
"},{"location":"config-params/#title_2","title":"title
","text":"The title of the page.
Type: String
"},{"location":"config-params/#kerkopagination","title":"kerko.pagination.
","text":""},{"location":"config-params/#page_len","title":"page_len
","text":"The number of search results per page.
Type: Integer Default value: 20
pager_links
","text":"Number of pages to show in the pager (not counting the current page).
Type: Integer Default value: 4
kerko.performance.
","text":""},{"location":"config-params/#whoosh_index_memory_limit","title":"whoosh_index_memory_limit
","text":"Maximum memory (in megabytes) the Whoosh index writer will use for the indexing pool. The higher the number, the faster indexing will be.
The actual memory used will be higher than this value because of interpreter overhead (up to twice as much!). Other operations performed by Kerko at indexing time use memory too. Thus, although useful as a tuning parameter, this setting does not allow to exactly control the memory usage.
Type: Integer Default value: 128
"},{"location":"config-params/#whoosh_index_processors","title":"whoosh_index_processors
","text":"Controls the number of processors Whoosh will use for indexing.
Note that when you use multiprocessing, the whoosh_index_memory_limit
parameter controls the amount of memory used by each process, so the actual memory used will be whoosh_index_memory_limit
\u00d7 whoosh_index_processors
.
Type: Integer Default value: 1
"},{"location":"config-params/#kerkoscopes","title":"kerko.scopes.*.
","text":"Keyword search scopes, where *
is a scope key. The scope key is used internally by Kerko to identify the scope. Scopes allow users to restrict the search to some fields.
The default scopes are:
all
creator
fulltext
metadata
pubyear
title
You may define additional scopes.
To link fields to scopes, see kerko.search_fields.scopes
.
breadbox_label
","text":"Label to use when the scope appears in the breadbox, i.e. in the list of search criteria.
"},{"location":"config-params/#enabled_3","title":"enabled
","text":"Enable the scope.
Type: Boolean
"},{"location":"config-params/#help_text_1","title":"help_text
","text":"Description of the scope, to show in the help window.
Type: String
"},{"location":"config-params/#selector_label","title":"selector_label
","text":"Label to use in the scope selector.
Type: String
"},{"location":"config-params/#weight_3","title":"weight
","text":"Relative position of the scope in lists. Scopes with low weights (small numbers) rise above heavier ones (large numbers).
Type: Integer
"},{"location":"config-params/#kerkosearch","title":"kerko.search.
","text":""},{"location":"config-params/#fulltext","title":"fulltext
","text":"Allow full-text search of PDF attachments.
Type: Boolean Default value: true
Tip
To get consistent results with full-text search, see Ensuring full-text indexing of your attachments in Zotero.
Tip
When setting kerko.search.fulltext
to false
, it is recommended that you set kerko.scopes.fulltext.enabled
and kerko.scopes.metadata.enabled
to false
as well. With full-text data unavailable, the fulltext
scope is useless, and the metadata
scope gives the same results as the all
scope.
Modifies the cache and the search index
Changing this parameter will require that you run the sync cache --full
and sync index
commands. See synchronization commands for details.
result_fields
","text":"List of item fields to retrieve for search results (most notably used by the kerko.templates.search_item
template).
Values in this list are keys identifying fields defined in the kerko.composer.Composer
instance. One probably only needs to change the default list when overriding the template to display additional fields.
Note that some fields from the default list may be required by Kerko, and removing those could cause crashes.
Type: Array of strings Default value: [\"id\", \"attachments\", \"bib\", \"coins\", \"data\", \"url\"]
whoosh_language
","text":"The language of search requests.
As of this writing, Whoosh supports the following languages: ar, da, nl, en, fi, fr, de, hu, it, no, pt, ro, ru, es, sv, tr. You may refer to Whoosh's source code to get the list of supported languages (see whoosh.lang.languages
) and the list of languages that support stemming (see whoosh.lang.has_stemmer()
).
Type: String Default value: \"en\"
Modifies the search index
Changing this parameter will require that you run the sync index --full
command. See synchronization commands for details.
kerko.search_fields.*.
","text":"Searchable fields, where *
is a field key. The default fields fall into different tables:
core.optional.*
: These fields have limited parameters. Their only allowed parameters are boost
, enabled
, and scopes
.core.required.*
: These fields cannot be disabled. Their only allowed parameters are boost
and scopes
.zotero.*
: These fields derive directly from Zotero item fields and allow all field parameters.The configuration system does not allow adding new fields.
Modifies the search index
Changing any of the kerko.search_fields.*
parameters will require that you run the clean index
and sync index
commands, except if you are just disabling a field or changing its scopes
parameter. See synchronization commands for details.
analyzer
","text":"Type of analysis to apply to the field value when building the search index.
Allowed values:
\"id\"
: Index the entire value of the field as one token.\"name\"
: Apply standard tokenization and filtering, but without stemming.\"text\"
: Apply standard tokenization, stemming and filtering.Type: String
"},{"location":"config-params/#boost","title":"boost
","text":"Scaling factor to apply to score when matches are found in the field.
Type: Float
"},{"location":"config-params/#enabled_4","title":"enabled
","text":"Enable the field.
Type: Boolean
"},{"location":"config-params/#scopes","title":"scopes
","text":"List of keyword search scopes that will exploit the field.
Allowed values are determined by kerko.scopes
.
Type: Array of strings
"},{"location":"config-params/#kerkosorts","title":"kerko.sorts.*.
","text":"Search results sorting options, where *
is a sort option key.
The default sort options are:
author_asc
author_desc
date_asc
date_desc
score
title_asc
title_desc
The configuration system does not allow adding new sort options.
"},{"location":"config-params/#enabled_5","title":"enabled
","text":"Enable the sort option.
Type: Boolean
"},{"location":"config-params/#label_1","title":"label
","text":"Label of the sort option.
Type: String
"},{"location":"config-params/#weight_4","title":"weight
","text":"Relative position of the sort option in lists. Sort options with low weights (small numbers) rise above heavier ones (large numbers).
The default sort option will be the one with the lowest weight.
Type: Integer
Tip
It is recommended that kerko.sorts.score.weight
has the smallest value of all your sort options. Thus, when a keyword search is performed, sorting by relevance score will be the default, and when no keywords are used in the search, then the sort option with the second smallest weight will be the default one.
kerko.templates.
","text":""},{"location":"config-params/#search","title":"search
","text":"Name of the Jinja2 template to render for the search page with list of results.
Type: String Default value: \"kerko/search.html.jinja2\"
search_item
","text":"Name of the Jinja2 template to render for the search page with a single bibliographic record.
Type: String Default value: \"kerko/search-item.html.jinja2\"
item
","text":"Name of the Jinja2 template to render for the bibliographic record view.
Type: String Default value: \"kerko/item.html.jinja2\"
atom_feed
","text":"Name of the Jinja2 template used to render an Atom feed.
Type: String Default value: \"kerko/atom.xml.jinja2\"
layout
","text":"Name of the Jinja2 template that is extended by the search, search-item, and item templates.
Type: String Default value: \"kerko/layout.html.jinja2\"
base
","text":"Name of the Jinja2 template that is extended by the layout template.
Type: String Default value: \"kerko/base.html.jinja2\"
kerko.zotero.
","text":""},{"location":"config-params/#attachment_mime_types","title":"attachment_mime_types
","text":"List of allowed MIME types for attachments.
Type: Array of strings Default value: [\"application/pdf\"]
Modifies the attachments
Changing this parameter will require that you run the sync attachments
command. See synchronization commands for details.
csl_style
","text":"The citation style to use for formatted references.
Allowed values are either a file name (without the .csl
extension) found in the Zotero Styles Repository (e.g., \"apa\"
) or the publicly accessible URL of a remote CSL file.
Type: String Default value: \"apa\"
.
Modifies the cache and the search index
Changing this parameter will require that you run the sync cache --full
and sync index
commands. See synchronization commands for details.
batch_size
","text":"Number of items to request on each call to the Zotero API.
Type: Integer Default value: 100
(this is the maximum currently allowed by the Zotero API)
child_include_re
","text":"Regular expression to use to include children (e.g. notes, attachments) based on their tags. Any child which does not have a tag that matches this regular expression will be ignored. If this value is empty (which is the default), all children will be accepted unless kerko.zotero.child_exclude_re
is set and causes some to be rejected.
Type: String Default value: \"\"
Modifies the search index and attachments
Changing this parameter will require that you run the sync index --full
and sync attachments
commands. See synchronization commands for details.
child_exclude_re
","text":"Regular expression to use to exclude children (e.g. notes, attachments) based on their tags. Any child that have a tag that matches this regular expression will be ignored. If empty, no children will be rejected unless kerko.zotero.child_include_re
is set and the tags of those children do not match it. By default, any child having at least one tag that begins with an underscore character (_
) is rejected.
Type: String Default value: \"^_\"
Modifies the search index and attachments
Changing this parameter will require that you run the sync index --full
and sync attachments
commands. See synchronization commands for details.
item_include_re
","text":"Regular expression to use to include items based on their tags. Any item which does not have a tag that matches this regular expression will be ignored. If this value is empty (which is the default), all items will be accepted unless kerko.zotero.item_exclude_re
is set which can cause some items to be rejected.
Type: String Default value: \"\"
Modifies the search index and attachments
Changing this parameter will require that you run the sync index --full
and sync attachments
commands. See synchronization commands for details.
item_exclude_re
","text":"Regular expression to use to exclude items based on their tags. Any item that have a tag that matches this regular expression will be excluded. If empty (which is the default), no items will be excluded unless kerko.zotero.item_include_re
is set, in which case items that do not have any tag that matches it will be excluded.
Type: String Default value: \"\"
Modifies the search index and attachments
Changing this parameter will require that you run the sync index --full
and sync attachments
commands. See synchronization commands for details.
locale
","text":"The locale to use with Zotero API calls. This dictates the locale of Zotero item types, field names, creator types and citations. Supported locales are listed at https://api.zotero.org/schema, under \"locales\".
Type: String Default value: \"en-US\"
Modifies the cache and the search index
Changing this parameter will require that you run the sync cache --full
and sync index
commands. See synchronization commands for details.
max_attempts
","text":"Maximum number of tries after the Zotero API has returned an error or has not responded during indexing.
Type: Integer Default value: 10
tag_include_re
","text":"Regular expression to use to include tags. By default, all tags are accepted.
Note that record exports (downloads) always include all tags regardless of this parameter, which only applies to information displayed by Kerko (exports are generated by the Zotero API, not by Kerko).
Type: String Default value: \"\"
Modifies the search index
Changing this parameter will require that you run the sync index --full
command. See synchronization commands for details.
tag_exclude_re
","text":"Regular expression to use to exclude tags. The default value causes any tag that begins with an underscore character (_
) to be ignored by Kerko.
Note that record exports (downloads) always include all tags regardless of this parameter, which only applies to information displayed by Kerko (exports are generated by the Zotero API, not by Kerko).
Type: String Default value: \"^_\"
Modifies the search index
Changing this parameter will require that you run the sync index --full
command. See synchronization commands for details.
wait
","text":"Time to wait (in seconds) between failed attempts to call the Zotero API.
Type: Integer Default value: 120
kerkoapp.proxy_fix.
","text":"When an application is running behind a proxy server, WSGI may see the request as coming from that server rather than the real client. Proxies set various headers to track where the request actually came from.
In that case you must tell the application how many proxies set each header so it knows what values to trust. However, enable this ONLY if the application is actually running behind a proxy; it would be a security issue to trust values that came directly from the client rather than a proxy.
Refer to Tell Flask it is behind a proxy for details.
Warning
This parameter is specific to KerkoApp.
"},{"location":"config-params/#enabled_6","title":"enabled
","text":"Enable the proxy parameters.
All other kerkoapp.proxy_fix
parameters are ignored unless this is set to true
.
Type: Boolean Default value: false
x_for
","text":"Number of values to trust for X-Forwarded-For
.
Type: Integer Default value: 1
x_proto
","text":"Number of values to trust for X-Forwarded-Proto
.
Type: Integer Default value: 1
x_host
","text":"Number of values to trust for X-Forwarded-Host
.
Type: Integer Default value: 0
x_port
","text":"Number of values to trust for X-Forwarded-Port
.
Type: Integer Default value: 0
x_prefix
","text":"Number of values to trust for X-Forwarded-Prefix
.
Type: Integer Default value: 0
This section provides guidance on how to contribute to the Kerko project.
"},{"location":"contributing/#reporting-issues","title":"Reporting issues","text":"Before reporting an issue, please consider the following guidelines:
Clone the Kerko repository into a local directory. Set up a virtual environment, then install that local version of Kerko in the virtual environment, including development and testing dependencies by running the following command from Kerko's root directory, i.e., where setup.cfg
resides:
pip install -e .[dev,docs,tests]\n
"},{"location":"contributing/#running-the-tests","title":"Running the tests","text":"To run the test suite:
python -m unittest\n
To check code coverage as well, use these commands instead:
coverage run -m unittest\ncoverage report\n
To run the full test suite under different environments (using the various Python interpreters available on your machine):
tox\n
Note
Test coverage is still low at the moment. You are welcome to contribute new tests!
"},{"location":"contributing/#running-the-pre-commit-hooks","title":"Running the pre-commit hooks","text":"Pre-commit checks should be performed automatically whenever you perform a git commit
. If you wish to run the checks manually, use this command:
pre-commit run --all-files\n
"},{"location":"contributing/#working-on-the-documentation","title":"Working on the documentation","text":"To start a local live-reloading documentation server:
mkdocs serve\n
Then view the documentation in your browser at http://localhost:8000/.
"},{"location":"contributing/#building-the-distribution-package","title":"Building the distribution package","text":"When building the distribution package, a version number is dynamically extracted from the Git repository. For an official release, the Git head revision must be tagged prior to building the distribution package. When the revision is not tagged, a dev version number gets derived from the branch's most recent tag, with a suffix appended.
To check the version number that will be generated:
hatch version\n
To build the distribution package in sdist and wheel formats:
hatch build\n
"},{"location":"contributing/#submitting-code-changes","title":"Submitting code changes","text":"Pull requests may be submitted against Kerko's repository. Please consider the following guidelines:
Some guidelines:
Please submit your translation as a pull request against the proper repository, either Kerko's, or KerkoApp's, or by e-mail, with the PO file included as an attachment (do not copy the PO file's content into an e-mail's body, since that could introduce formatting or encoding issues).
"},{"location":"contributing/#supporting-the-project","title":"Supporting the project","text":"Nurturing an open source project, following up on issues and helping others in working with the system is a lot of work. Hiring the original developers of Kerko can help make the project sustainable. It is the best way to ensure continued support and development of the project.
If you need professional support related to Kerko, have requirements not currently implemented in Kerko, want to make sure that some Kerko issue important to you gets resolved, or if you just like our work and would like to hire us for an unrelated project, please e-mail us.
"},{"location":"deploying/","title":"How to deploy","text":"As there is a great diversity of operating systems, hosting environments, and WSGI servers, it is hard to provide universal and useful instructions for setting up KerkoApp for use in production.
You can expect a procedure similar to that of any Flask application, and there are many guides on the web covering this topic for various environments.
That said, you may refer to the guide below for step-by-step instructions. Even if your environment is different from the one this guide was designed for, it might provide you with some useful hints.
"},{"location":"deploying/#deploying-on-ubuntu-2004-or-2204-with-nginx-and-gunicorn","title":"Deploying on Ubuntu 20.04 or 22.04 with nginx and gunicorn","text":"These instructions will detail the steps and configurations required to get KerkoApp running on an Ubuntu 20.04 or 22.04 web server, using Gunicorn as the WSGI container and nginx as a HTTP proxy.
The procedure is similar that of any Flask application, but KerkoApp-specific steps are also covered here.
Install some required packages, including Python 3:
sudo apt install git nginx python3 python3-pip python3-venv\n
Create the user who will run the app:
sudo groupadd --system kerkoapp\nsudo useradd --gid kerkoapp --shell /bin/bash --create-home --home-dir /home/kerkoapp --groups www-data kerkoapp\n
Switch to that user and clone the desired version of KerkoApp. If you want to use version 1.0.0, for example, replace VERSION
in the command below with 1.0.0
:
sudo su kerkoapp\ngit clone --branch VERSION https://github.com/whiskyechobravo/kerkoapp.git ~/kerkoapp\n
Still as user kerkoapp
, create a Python virtual environment and install the Python packages required by KerkoApp:
python3 -m venv ~/venv\nsource ~/venv/bin/activate\npip3 install -r ~/kerkoapp/requirements/run.txt\npip3 install gunicorn\n
Always as user kerkoapp
, create the ~/.secrets.toml
file. This is where you will put secret keys that should only be known to your server. Its content should look like the following:
SECRET_KEY = \"MY_SECRET_KEY\"\nZOTERO_API_KEY = \"MY_ZOTERO_API_KEY\"\n
You must set SECRET_KEY
with a random string, and ZOTERO_API_KEY
with an appropriate value (see configuration parameters).
Then create the ~/instance.toml
file. This file will contain settings that are specific to your server, but are not secret. Its content should look like the following:
LOGGING_HANDLER = \"syslog\"\n\n[kerkoapp.proxy_fix]\nenabled = true\nx_for = 1\nx_proto = 1\nx_host = 1\nx_port = 0\nx_prefix = 0\n
We are enabling the kerkoapp.proxy_fix
parameters because we will configure nginx as a reverse proxy.
Then create the ~/config.toml
file. This file will contain general settings for Kerko. You might have already tested KerkoApp on your desktop computer and created such file. If so, you could just copy that file to your server. At the very least it should contain the following settings:
ZOTERO_LIBRARY_ID = \"MY_ZOTERO_LIBRARY_ID\"\nZOTERO_LIBRARY_TYPE = \"MY_ZOTERO_LIBRARY_TYPE\"\n\n[kerko.meta]\ntitle = \"My Bibliography\"\n
You must set ZOTERO_LIBRARY_ID
and ZOTERO_LIBRARY_TYPE
with appropriate values (see configuration parameters) so that Kerko can connect to your Zotero library.
It is not absolutely necessary to use three separate configuration files for KerkoApp as we just did. You could, for example, have just ~/instance.toml
and put all of the settings there. However, it is a good practice to split the configuration, and that allows you to copy config.toml
from or to other machines, or even share it with other people, without worrying about leaking secret keys or messing up your server-specific settings.
Once the configuration files are ready, Kerko should be able to talk to Zotero. Have Kerko retrieve your Zotero library's data by running the following command:
flask --debug kerko sync\n
The --debug
switch is optional. If you use it, some messages will give you an better idea of the progress of the sync process. If you omit it, the command will run silently unless there are warnings or errors.
Depending on the size of your library, this process can complete within less than a minute or take an hour or more. Zotero throttles API requests to prevent its servers from getting overloaded, so sometimes the process might seem to freeze, but be patient and Kerko will resume synchronization a few minutes later.
Now that synchronization works, configure the cron task that will synchronize data from your Zotero library on a regular basis. Run the following command (always from the kerkoapp
user):
crontab -e\n
That will launch the default nano
editor. Add the following line at the very bottom, then save the file and exit the editor:
10 4 * * * cd /home/kerkoapp/kerkoapp && /home/kerkoapp/venv/bin/flask kerko sync\n
That will synchronize the data once a day, at 4:10am. You may specify a different time, of course.
Now exit from the kerkoapp
user's shell, and go back to your usual sudoer account to finish the installation.
Configure a socket that will let Gunicorn to speak with nginx. As the superuser, create the /etc/systemd/system/kerkoapp.socket
file, with the following content:
[Unit]\nDescription=KerkoApp socket\n\n[Socket]\nListenStream=/run/kerkoapp.socket\n\n[Install]\nWantedBy=kerkoapp.target\n
Configure a service that will run Gunicorn. As the superuser, create the /etc/systemd/system/kerkoapp.service
file, with the following content:
[Unit]\nDescription=KerkoApp daemon\nRequires=kerkoapp.socket\nAfter=network.target\n\n[Service]\nWorkingDirectory=/home/kerkoapp/kerkoapp\nExecStart=/home/kerkoapp/venv/bin/gunicorn wsgi:app --name kerkoapp --user kerkoapp --group www-data --workers 4 --log-level warning --error-logfile - --access-logfile - --bind unix:/run/kerkoapp.socket\nExecReload=/bin/kill -s HUP $MAINPID\nExecStop=/bin/kill -s TERM $MAINPID\nPrivateTmp=true\n\n[Install]\nWantedBy=multi-user.target\n
Reload the systemd configurations, then enable and start the new service by running the following commands:
sudo systemctl daemon-reload\nsudo systemctl enable kerkoapp.socket\nsudo systemctl enable kerkoapp.service\nsudo systemctl start kerkoapp.socket\n
You can check whether the socket is active with this command:
sudo systemctl status kerkoapp.socket\n
If it shows up as 'active (listening)', you may now verify that it triggers the service:
curl --unix-socket /run/kerkoapp.socket localhost\nsudo systemctl status kerkoapp.service\n
The curl
command should output some HTML, and the systemctl
command should now show the KerkoApp daemon as 'active (running)'.
If either the socket or the service doesn't work, you might want to check for errors in the log:
sudo journalctl --unit=kerkoapp\n
Once all of the above works, configure nginx to pass requests to Gunicorn. As the superuser, create the /etc/nginx/sites-available/kerkoapp.conf
file with the following content, replacing example.com
with your actual domain name:
server {\n listen 80;\n server_name example.com;\n\n location / {\n proxy_redirect off;\n proxy_set_header Host $http_host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Host $server_name;\n proxy_set_header X-Forwarded-Proto $scheme;\n\n if (!-f $request_filename) {\n proxy_pass http://unix:/run/kerkoapp.socket;\n break;\n }\n }\n}\n
Enable the site by running the following command:
sudo ln -s /etc/nginx/sites-available/kerkoapp.conf /etc/nginx/sites-enabled/\n
Have nginx test the configuration:
sudo nginx -t\n
If the command reports the configuration test as successful, reload nginx to make the configuration changes effective:
sudo service nginx reload\n
You should now be able to view your KerkoApp site at http://example.com!
The nginx configuration above will serve the application using the HTTP protocol. As for any website, HTTPS is strongly recommended. That will require that you install a SSL certificate and configure nginx to use it; that exercise is left to the reader.
Changing the configuration can be disruptive
Making any change to a configuration file requires that you at least restart the application afterwards for the change to become effective.
Moreover, some parameters have an effect on the structure of the cache or the search index that Kerko depends on. Changing this kind of parameter may require that you rebuild either. Refer to the documentation of the parameter to check if specific actions need to be taken after a change.
The commands below, for example, will allow you to clean and rebuild the search index, and to restart KerkoApp:
sudo -iu kerkoapp bash -c 'cd /home/kerkoapp/kerkoapp && /home/kerkoapp/venv/bin/flask kerko clean index'\nsudo -iu kerkoapp bash -c 'cd /home/kerkoapp/kerkoapp && /home/kerkoapp/venv/bin/flask kerko sync'\nsudo systemctl stop kerkoapp.socket\nsudo systemctl start kerkoapp.socket\n
"},{"location":"deploying/#submitting-your-sitemap-to-search-engines","title":"Submitting your sitemap to search engines","text":"Kerko generates an XML Sitemap that can help search engines discover your bibliographic records.
The path of the sitemap is BASE_URL/sitemap.xml
, where BASE_URL
should be replaced with the protocol, domain, port, and Kerko URL path prefix that are relevant to your installation, e.g., https://example.com/bibliography/sitemap.xml
.
Different search engines may have different procedures for submitting sitemaps (Google, Bing, Yandex).
However, a standard method consists in adding a Sitemap
directive to a robots.txt
file served at the root of your site, to tell web crawlers where to find your sitemap. For example, one might add the following line to robots.txt
:
Sitemap: https://example.com/bibliography/sitemap.xml\n
A robots.txt
file can have multiple Sitemap
directives, thus the Kerko sitemap can be specified alongside any other sitemaps you might already have.
For getting started with Kerko, we recommend that you use KerkoApp. However, if KerkoApp is not suited to your use case, we also have instructions for creating a custom application.
"},{"location":"getting-started/#getting-started-with-kerkoapp","title":"Getting started with KerkoApp","text":"To install KerkoApp, you may choose between a \"standard\" installation and a Docker installation. Just go with the option you feel most comfortable with. If you don't know Docker, you should be fine with the standard installation. But if you prefer to keep your distance from Python-related stuff, perhaps the Docker installation will suit you best.
"},{"location":"getting-started/#standard-installation","title":"Standard installation","text":"This procedure requires that you have Python, pip, and Git installed on your computer.
The first step is to install the desired version of KerkoApp. You may check the list of available versions, but make sure to choose one that matches the documentation version you are currently reading! For version 1.0.0, for example, replace VERSION
with 1.0.0
in the commands below:
git clone --branch VERSION https://github.com/whiskyechobravo/kerkoapp.git\ncd kerkoapp\npython -m venv venv\nsource venv/bin/activate\npip install -r requirements/run.txt\n
git clone --branch VERSION https://github.com/whiskyechobravo/kerkoapp.git\ncd kerkoapp\npython -m venv venv\nvenv\\Scripts\\activate.bat\npip install -r requirements\\run.txt\n
This will install all packages required by Kerko and KerkoApp within a virtual environment.
Copy the sample.secrets.toml
file to .secrets.toml
in the same directory. Open .secrets.toml
in a text editor to assign proper values to the parameters outlined below:
SECRET_KEY
: This parameter is required for generating secure tokens in web forms. It should have a hard to guess value, and should really remain secret. For this reason, never add your .secrets.toml
file to a code repository.ZOTERO_API_KEY
: Your Zotero API key. See API key creation instructions.Copy the sample.config.toml
file to config.toml
in the same directory. Open config.toml
in a text editor to assign proper values to the parameters outlined below:
ZOTERO_LIBRARY_ID
: The identifier of the Zotero library to get data from. For a personal library the value is your userID, as found on https://www.zotero.org/settings/keys (you must be logged-in). For a group library this value is the groupID of the library, as found in the URL of the library (e.g., the groupID of the library at https://www.zotero.org/groups/2348869/kerko_demo is \"2348869\"
).ZOTERO_LIBRARY_TYPE
: The type of library to get data from, either \"user\"
for a personal library, or \"group\"
for a group library.You do not need to edit other parameters at this point, but later on config.toml
is where your configuration changes will take place.
Have KerkoApp synchronize your data from zotero.org:
flask --debug kerko sync\n
If you have a large Zotero library and/or large file attachments, that command may take a while to complete. Wait until the command finishes. In production use, this command is usually added to the crontab file for regular execution.
The --debug
switch is optional. If you use it, some messages will give you an idea of the sync process' progress. If you omit it, the command will run silently unless there are warnings or errors.
To list all commands provided by Kerko:
flask kerko --help\n
Run KerkoApp:
flask --debug run\n
Open http://localhost:5000/ in your browser and explore the bibliography!
Running your installed application
To launch the application again in a future session, make sure to reactivate the virtual environment first. The command sequence should look like:
POSIXWindowscd kerkoapp\nsource venv/bin/activate\nflask --debug run\n
cd kerkoapp\nvenv\\Scripts\\activate.bat\nflask --debug run\n
Not suitable for production
The above procedure relies on Flask's built-in server, which is not suitable for production. For production use, you should consider better options such as the WSGI servers suggested in the Flask documentation.
"},{"location":"getting-started/#docker-installation","title":"Docker installation","text":"This procedure requires that Docker is installed on your computer.
Copy the Makefile
, sample.secrets.toml
, and sample.config.toml
files from the most recent stable branch of the KerkoApp repository (e.g. https://github.com/whiskyechobravo/kerkoapp/tree/stable/1.0.x) to an empty directory on your computer.
Under the same directory, create a subdirectory named instance
. This is where you will put your configuration files, and where Kerko will save its data.
Copy sample.secrets.toml
as .secrets.toml
into the instance
subdirectory. Open instance/.secrets.toml
in a text editor to assign proper values to the configuration parameters outlined below:
SECRET_KEY
: This parameter is required for generating secure tokens in web forms. It should have a hard to guess value, and should really remain secret. For this reason, never add your .secrets.toml
file to a code repository.ZOTERO_API_KEY
: Your Zotero API key. See API key creation instructions.Copy sample.config.toml
as config.toml
into the instance
subdirectory. Open instance/config.toml
in a text editor to assign proper values to the configuration parameters outlined below:
ZOTERO_LIBRARY_ID
: The identifier of the Zotero library to get data from. For a personal library the value is your userID, as found on https://www.zotero.org/settings/keys (you must be logged-in). For a group library this value is the groupID of the library, as found in the URL of the library (e.g., the groupID of the library at https://www.zotero.org/groups/2348869/kerko_demo is \"2348869\"
).ZOTERO_LIBRARY_TYPE
: The type of library to get data from, either \"user\"
for a personal library, or \"group\"
for a group library.It should not be necessary to change other settings at this point. You can always come back later to this file in order to configure KerkoApp to your liking. For now, we suggest that you proceed to the next step and get it running.
From the same directory as Makefile
, run KerkoApp:
make run\n
This command should do many things:
If your configuration files have errors, the process may be interrupted; if that happens, retry make run
after correcting the problem. Otherwise, if all goes well, you will only have to wait a bit for the data synchronization process to complete. This may take a long time if you have a large Zotero library.
Kerko's data will be stored in the instance
subdirectory.
KerkoApp should launch once the synchronization process has completed. When you see the following message in the terminal, proceed to the next step:
[INFO] Listening at: http://0.0.0.0:80\n
Open http://localhost:8080/ in your browser and explore the bibliography!
To stop the KerkoApp server, press Ctrl+C in the terminal where the container is running.
The next time you execute make run
, it will find that the image has been already been downloaded and the data synchronized, and thus it will just launch the server.
Using the Kerko command line interface (CLI) with Docker
To use Kerko's command line interface, enter this command from the same directory as Makefile
:
make shell\n
This will start an interactive shell within the Docker container. From there, you may run Kerko commands to clean Kerko's data, to synchronize from zotero.org, or to check Kerko's configuration. The command below lists all the commands provided by Kerko:
flask kerko --help\n
To exit the interactive shell, enter exit
or press Ctrl+D at the command prompt.
Building a Docker image for production
The Makefile
is just an example that shows how to build and interact with a dockerized KerkoApp. For production use, you might want to clone the full KerkoApp repository, make some changes to its Dockerfile
, and build your own image.
For full documentation on how to run Docker containers, including port mapping and volume binding, see the Docker documentation.
"},{"location":"getting-started/#creating-a-custom-application","title":"Creating a custom application","text":"This section should help you understand the minimal steps required for setting up Kerko within a custom Flask application.
Tip
For a ready-to-use standalone application, you will be better off using KerkoApp instead.
Some familiarity with Flask should help you make more sense of the instructions, but should not be absolutely necessary for getting them to work. Let's now build a minimal app:
Create an empty directory myapp
where your application reside.
Install Kerko in a new virtual environment:
POSIXWindowscd myapp\npython -m venv venv\nsource venv/bin/activate\npip install kerko\n
cd myapp\npython -m venv venv\nvenv\\Scripts\\activate.bat\npip install kerko\n
In the myapp
directory, create a file named .env
, where parameters required by Kerko will be configured, with content such as the example below:
MYAPP_SECRET_KEY=\"your-random-secret-key\"\nMYAPP_ZOTERO_API_KEY=\"xxxxxxxxxxxxxxxxxxxxxxxx\"\nMYAPP_ZOTERO_LIBRARY_ID=\"9999999\"\nMYAPP_ZOTERO_LIBRARY_TYPE=\"group\"\n
Replace each value with a proper one. The meaning of each parameter is outlined below:
MYAPP_SECRET_KEY
: This parameter is required for generating secure tokens in web forms. It should have a hard to guess value, and should really remain secret. For this reason, never add your .env
file to a code repository.MYAPP_ZOTERO_API_KEY
: Your Zotero API key. See API key creation instructions.MYAPP_ZOTERO_LIBRARY_ID
: The identifier of the Zotero library to get data from. For a personal library the value is your userID, as found on https://www.zotero.org/settings/keys (you must be logged-in). For a group library this value is the groupID of the library, as found in the URL of the library (e.g., the groupID of the library at https://www.zotero.org/groups/2348869/kerko_demo is \"2348869\"
).MYAPP_ZOTERO_LIBRARY_TYPE
: The type of library to get data from, either \"user\"
for a personal library, or \"group\"
for a group library.A .env
file is a good place to store an application's secrets. It is good practice to keep this file only on the machine where the application is hosted, and to never push it to a code repository.
Create a file named wsgi.py
with the following content:
import kerko\nfrom flask import Flask\nfrom flask_babel import Babel\nfrom flask_bootstrap import Bootstrap4\nfrom kerko.composer import Composer\nfrom kerko.config_helpers import config_set, config_update, validate_config\n\napp = Flask(__name__)\n
The above imports required modules and creates the Flask application object (app
). Then, load the default Kerko configuration, and update it from values set in .env
:
# Initialize app configuration with Kerko's defaults.\nconfig_update(app.config, kerko.DEFAULTS)\n\n# Update app configuration from environment variables.\napp.config.from_prefixed_env(prefix=\"MYAPP\")\n
Next, adjust general application parameters to your liking. For example, we can use the config_set
function to set the main title of the web application to \"My App\"
. This function can be called each time you wish to set a configuration option.
# Make changes to the Kerko configuration here, if desired.\nconfig_set(app.config, \"kerko.meta.title\", \"My App\")\n
Next, have Kerko parse and validate the configuration. Then create the kerko_composer
object, which provides key elements needed by Kerko such as the fields to display and search, and the facets made available for filtering:
# Validate configuration and save its parsed version.\nparse_config(app.config)\n\n# Initialize the Composer object.\napp.config[\"kerko_composer\"] = Composer(app.config)\n\n# Make changes to the Kerko composer object here, if desired.\n
Using methods of the Composer
class, your application could alter the kerko_composer
object if needed, to add, remove or alter fields, facets, sort options, search scopes, record download formats, or badges.
Finally, initialize extensions required by Kerko (see the respective documentations of Flask-Babel and Bootstrap-Flask for more details), and register the Kerko blueprint with the application object:
wsgi.pybabel = Babel(app)\nbootstrap = Bootstrap4(app)\n\napp.register_blueprint(kerko.make_blueprint(), url_prefix=\"/bibliography\")\n
The url_prefix
argument given above defines the base path for every URL provided by Kerko.
Note
The full code example is available on GitHub.
In the same directory as wsgi.py
with your virtual environment active, run the following shell commands:
flask --debug kerko sync\n
If you have a large Zotero library and/or large file attachments, that command may take a while to complete. Wait until the command finishes. In production use, this command is usually added to the crontab file for regular execution.
The --debug
switch is optional. If you use it, some messages will give you an idea of the sync process' progress. If you omit it, the command will run silently unless there are warnings or errors.
To list all commands provided by Kerko:
flask kerko --help\n
Run your application:
flask --debug run\n
Open http://127.0.0.1:5000/bibliography/ in your browser and explore the bibliography!
You have just built a really minimal application for Kerko. However, if you are looking at developing a custom Kerko application, we recommend that you still look at KerkoApp for a more advanced starting point. While still small, KerkoApp adds some structure as well as features such as TOML configuration files, translations loading, a syslog logging handler, and error pages.
"},{"location":"localization/","title":"Localization","text":"This section is about adapting Kerko for specific regions or languages. For this purpose, the main issues to consider are:
BABEL_DEFAULT_LOCALE
. If no translation is available for the desired language, or if the existing translation needs to be updated, see Translating Kerko and Translating KerkoApp below.BABEL_DEFAULT_TIMEZONE
.kerko.zotero.locale
.kerko.search.whoosh_language
.Kerko translations are managed with Babel.
The following commands should be executed from the root Kerko directory (the one that contains babel.cfg
), and the virtual environment must have been activated beforehand.
Create or update the PO template (POT) file. Replace CURRENT_VERSION
with the current Kerko version:
pybabel extract -F babel.cfg -o src/kerko/translations/kerko.pot --project=Kerko --version=CURRENT_VERSION --copyright-holder=\"Kerko Contributors\" src/kerko\n
Create a new PO file (for a new locale) based on the POT file. Replace YOUR_LOCALE
with the appropriate language code, e.g., de
, es
, fr
:
pybabel init -l YOUR_LOCALE -D kerko -i src/kerko/translations/kerko.pot -d src/kerko/translations\n
Update an existing PO file based on the POT file:
pybabel update -l YOUR_LOCALE -D kerko -i src/kerko/translations/kerko.pot -d src/kerko/translations\n
Compile MO files:
pybabel compile -l YOUR_LOCALE -D kerko -d src/kerko/translations --statistics\n
Contributing your translation
You are welcome to contribute your translation. See Submitting a translation. It is only thanks to user contributions that Kerko is available in multiple languages.
"},{"location":"localization/#translating-kerkoapp","title":"Translating KerkoApp","text":"Although most user interface messages come from Kerko, KerkoApp also has messages of its own, and thus its own separate translation file.
KerkoApp translations are managed with Babel.
The following commands should be executed from the root KerkoApp directory (the one that contains babel.cfg
), and the virtual environment must have been activated beforehand.
Create or update the PO file template (POT). Replace CURRENT_VERSION
with your current KerkoApp version:
pybabel extract -F babel.cfg -o kerkoapp/translations/messages.pot --project=KerkoApp --version=CURRENT_VERSION --copyright-holder=\"Kerko Contributors\" kerkoapp\n
Create a new PO file (for a new locale) based on the POT file. Replace YOUR_LOCALE
with the appropriate language code, e.g., de
, es
, it
:
pybabel init -l YOUR_LOCALE -i kerkoapp/translations/messages.pot -d kerkoapp/translations\n
Update an existing PO file based on the POT file:
pybabel update -l YOUR_LOCALE -i kerkoapp/translations/messages.pot -d kerkoapp/translations\n
Compile MO files:
pybabel compile -l YOUR_LOCALE -d kerkoapp/translations\n
"},{"location":"synchronization/","title":"Synchronization","text":"Kerko synchronizes its data from Zotero through a 3-step process:
The first step is an incremental update of the cache, which is a local copy of the library. To this end, Kerko uses the Zotero API to request items and collections from the library on zotero.org. Unless the library is getting synchronized for the first time by Kerko, this will only request new and changed items from Zotero in order to reduce the number of API requests.
The second step reads data from the cache to update the search index. If the cache has changed since the last update, a full update of the search index is performed. No Zotero API calls are made during this step. Any changes to the search index are only committed at the end of this step, thus while the update is taking place users still see the data as it was prior to the synchronization run.
The third and last step reads the list of file attachments from the search index, with their MD5 hashes. It compares the hashes with those of the available local copies of the files, and downloads new or changed files from Zotero. It also deletes any local files that may no longer be used.
Usually, all synchronization steps should be executed. But under certain circumstances it can be useful to run a specific step alone. For example, after changing certain configuration settings, instead of cleaning all data and performing a lengthy full synchronization from Zotero, one may clean just the search index and rebuild it from the cache.
Note
The synchronization process is unidirectional, where Kerko pulls data from Zotero. Kerko will never try to write anything to your Zotero library.
"},{"location":"synchronization/#command-line-interface-cli","title":"Command line interface (CLI)","text":"Kerko provides an integration with the Flask command line interface. The flask
command will work with your virtual environment active.
Before running a command, go to the application's directory (where the wsgi.py
file is found). That is the easiest way to help Flask discover the application.
Some frequently used commands are:
flask kerko --help
Lists all commands provided by Kerko.
flask kerko sync
Synchronizes everything: the cache (from Zotero), the search index (from the cache), the attachments (from files in Zotero, based on list in search index).
Tip: Making commands more verbose
The --debug
option may be used with any Flask command and will cause Kerko to output more information. It will tell quite a bit more about what is happening during the synchronization process. For example:
flask --debug kerko sync\n
flask kerko sync --help
Shows help specifically about the sync
command:
flask kerko sync index
Synchronizes just the search index (from the cache).
flask kerko sync cache --full
When possible, the synchronization process performs an incremental update of just the new or changed items. Here, the --full
option forces a full synchronization of the cache, even if no or just some items have been updated since the last synchronization of the cache.
This can be useful after changing certain configuration parameters.
flask kerko clean everything
Deletes all of Kerko's data: cache, search index, attachments.
flask kerko clean --help
Shows help about the clean command.
flask kerko clean cache
Deletes just the cache. A subsequent execution of flask kerko sync
will perform a full update from Zotero, but it will not re-download all file attachments.
This does not affect the search index. Thus, if the index was built before a clean cache
, users will still be able to access the bibliography using the Kerko web interface.
flask kerko clean index
Deletes just the search index. The bibliography will become unavailable to the Kerko web interface until the index gets synchronized again.
It can be necessary to use this command after changing certain configuration parameters, and you will usually want to run flask kerko sync index
immediately after.
flask kerko config
Output a consolidated view of all configuration parameters, from all of your configuration files, and including the defaults provided by Kerko that you may not have explicitly configured.
"},{"location":"synchronization/#monitoring-data-synchronization","title":"Monitoring data synchronization","text":"Kerko provides a web API endpoint that you could use to monitor data synchronization.
In the description below, BASE_URL
should be replaced with the protocol, domain, port, and Kerko URL path prefix that are relevant to your installation, e.g., https://example.com/bibliography
.
The web API endpoint is:
BASE_URL/api/last-sync
Returns a JSON object with information about the last synchronization from Zotero. If no sync has been performed yet, it returns an empty JSON object, otherwise the returned object contains the following values:
hours_ago
Number of hours since the last sync.
when
ISO 8601 date string with the date and time of the last sync.
Sample JSON output{\n \"hours_ago\": 17.029,\n \"when\": \"2023-05-24T11:10:29.093335-04:00\"\n}\n
"},{"location":"troubleshooting/","title":"Troubleshooting","text":""},{"location":"troubleshooting/#no-such-command-kerko-error-when-running-flask","title":"No such command \"kerko\" error when running Flask","text":"Make sure to run the flask
command from the application's directory (where the wsgi.py
file is found).
To run it from other directories, you could use the --app
option, or to set the FLASK_APP
environment variable. See application discovery for details.
For example:
flask --app=/path/to/kerkoapp/wsgi:app kerko sync\n
"},{"location":"troubleshooting/#configuration-parameter-change-has-no-effect","title":"Configuration parameter change has no effect","text":"Restart the application. This is required for any configuration change to take effect.
If the change still appears to have no effect after a restart, use the following command to verify that the desired parameter value is actually being used:
flask --debug kerko config\n
If the parameter's value is not the expected one, check your configuration files. If you are uncertain about which configuration files are being loaded by the application, check the first few lines printed by the above command; these list the TOML files in their loading order. Remember that a later file can override values set in a previous one. If you are still unable to trace the source of an incorrect parameter value, check your environment variables. Environment variables can override parameter values set in TOML configuration files.
If, on the other hand, the parameter's value is the desired one, then review the documentation for that parameter. Make sure you understand the effect of the parameter value, and check for any notes or warnings. Some parameters require a rebuild of the cache or the search index to become effective.
"},{"location":"troubleshooting/#custom-application-conflicting-package-versions-with-standard-installation","title":"Custom application: Conflicting package versions with standard installation","text":"The requirements/run.txt
file specifies a precise version for each required package, ensuring consistent results with the last environment KerkoApp was tested with. If some of these packages are already present in your Python environment, their versions are likely to be different and some Python code outside KerkoApp might require those versions. In that case, try replacing run.txt
with run.in
in the install command:
pip install -r requirements/run.in\n
Requirements in run.in
are more flexible regarding the versions. If you still have version conflicts with those requirements, you'll have to find out which version to use, checking that it is compatible with both KerkoApp and your other Python code.
Before attempting any upgrade, it is highly recommended that you do a backup of all of your code, configuration files, data files, and Python virtual environment.
"},{"location":"upgrading/#from-10x-to-11x-or-12x","title":"From 1.0.x to 1.1.x or 1.2.x","text":""},{"location":"upgrading/#kerkoapp","title":"KerkoApp","text":"The instructions below make the assumption that you have cloned KerkoApp from its Git repository.
Get the desired version of KerkoApp. You may check the list of available versions. For version 1.1.0, for example, replace VERSION
with 1.1.0
in the command below:
git fetch && git checkout VERSION\n
Activate your Python virtual environment.
Install Python dependencies:
pip install --force-reinstall -r requirements/run.txt\n
Adapt your configuration file:
kerko.feeds.fields
parameter is either omitted or has at least the following values: [\"id\", \"data\", \"item_fields\"]
.Rebuild your search index using the following commands:
flask kerko clean index\nflask kerko sync index\n
Restart the application.
If you have a custom application, the following changes will need to be applied:
The application is now responsible for instantiating the blueprint by calling kerko.make_blueprint()
. Any previous uses of the global kerko.blueprint
object must be replaced, as Kerko no longer provides it. If registration was your application's only use of that object, the change could look like:
app.register_blueprint(kerko.blueprint, url_prefix='/bibliography')\n
Afterapp.register_blueprint(kerko.make_blueprint(), url_prefix='/bibliography')\n
... where app
is the Flask
object.
Version 1.0.x brings significant changes on how Kerko can be configured. Before you attempt an upgrade, reading Configuration basics is a must.
"},{"location":"upgrading/#kerkoapp_1","title":"KerkoApp","text":"The instructions below make the assumption that you have cloned KerkoApp from its Git repository.
Rename the default branch of your local KerkoApp repository:
git branch -m master main\ngit fetch origin\ngit branch -u origin/main main\ngit remote set-head origin -a\n
Get the desired version of KerkoApp. You may check the list of available versions. For version 1.0.0, for example, replace VERSION
with 1.0.0
in the command below:
git checkout VERSION\n
Activate your Python virtual environment.
Install Python dependencies:
pip install --force-reinstall -r requirements/run.txt\n
Rename the .env
file to dotenv.old
. We no longer want KerkoApp to use that file, but it might be useful to keep it as reference while we migrate the configuration.
.secrets.toml
and config.toml
, in the KerkoApp directory, i.e., the directory where wsgi.py
is found.SECRET_KEY
and KERKO_ZOTERO_API_KEY
lines from dotenv.old
into .secrets.toml
. In .secrets.toml
, rename the KERKO_ZOTERO_API_KEY
parameter to ZOTERO_API_KEY
. For each of the two parameters, make sure the value following the equal sign (=
) is surrounded by double quotes (\"
). To ascertain the syntax, you may have a look at the sample.secrets.toml
file provided by KerkoApp.dotenv.old
to config.toml
. For each parameter, use the list below to determine if something special needs to be done to migrate it. Almost all configuration parameters have been renamed and/or moved into a hierarchical structure (indicated by an arrow (\u2192)). Check the parameter values too as the syntax of a TOML file is slightly different from that of a .env
file, e.g., in TOML string values must be surrounded by double quotes (\"
), and booleans values must be either true
or false
(lowercase, no quotes). Refer to the parameters documentation for additional information, and have a look at the sample.config.toml
file provided by KerkoApp.DEBUG
: Remove. Debug mode is now activated with the --debug
command line option.FLASK_APP
: Probably not needed anymore. In doubt, please refer to the Flask documentation on application discovery. If you do need this variable, then a .env
file could be the right place. It will not work from a TOML file. Note also that the application is now referenced as wsgi.app
instead of kerkoapp.app
.FLASK_ENV
: Remove. Flask 2.3 stopped supporting it. Debug mode is now activated with the --debug
command line option.KERKO_BOOTSTRAP_VERSION
\u2192 kerko.assets.bootstrap_version
KERKO_CSL_STYLE
\u2192 kerko.zotero.csl_style
KERKO_COMPOSER
\u2192 kerko_composer
KERKO_DATA_DIR
\u2192 DATA_PATH
. Now optional, relative to the instance path, and defaulting to kerko
instead of data/kerko
.KERKO_DOWNLOAD_ATTACHMENT_NEW_WINDOW
\u2192 kerko.features.download_attachment_new_window
KERKO_DOWNLOAD_CITATIONS_LINK
\u2192 kerko.features.download_results
KERKO_DOWNLOAD_CITATIONS_MAX_COUNT
\u2192 kerko.features.download_results_max_count
KERKO_FEEDS
\u2192 kerko.feeds.formats
KERKO_FEEDS_FIELDS
\u2192 kerko.feeds.fields
KERKO_FEEDS_MAX_DAYS
\u2192 kerko.feeds.max_days
KERKO_FEEDS_REJECT_ANY
\u2192 kerko.feeds.reject_any
KERKO_FEEDS_REQUIRE_ANY
\u2192 kerko.feeds.require_any
KERKO_FULLTEXT_SEARCH
\u2192 kerko.search.fulltext
KERKO_HIGHWIREPRESS_TAGS
\u2192 kerko.meta.highwirepress_tags
KERKO_JQUERY_VERSION
\u2192 kerko.assets.jquery_version
KERKO_PAGE_LEN
\u2192 kerko.pagination.page_len
KERKO_PAGER_LINKS
\u2192 kerko.pagination.pager_links
KERKO_POPPER_VERSION
\u2192 kerko.assets.popper_version
KERKO_PRINT_CITATIONS_LINK
\u2192 kerko.features.print_results
KERKO_PRINT_CITATIONS_MAX_COUNT
\u2192 kerko.features.print_results_max_count
KERKO_PRINT_ITEM_LINK
\u2192 kerko.features.print_item
KERKO_RELATIONS_INITIAL_LIMIT
\u2192 kerko.features.relations_initial_limit
KERKO_RELATIONS_LINKS
\u2192 kerko.features.relations_links
KERKO_RELATIONS_SORT
\u2192 kerko.features.relations_sort
KERKO_RESULTS_ABSTRACTS
\u2192 kerko.features.results_abstracts
KERKO_RESULTS_ABSTRACTS_MAX_LENGTH
\u2192 kerko.features.results_abstracts_max_length
KERKO_RESULTS_ABSTRACTS_MAX_LENGTH_LEEWAY
\u2192 kerko.features.results_abstracts_max_length_leeway
KERKO_RESULTS_ABSTRACTS_TOGGLER
\u2192 kerko.features.results_abstracts_toggler
KERKO_RESULTS_ATTACHMENT_LINKS
\u2192 kerko.features.results_attachment_links
KERKO_RESULTS_FIELDS
\u2192 kerko.search.result_fields
KERKO_RESULTS_URL_LINKS
\u2192 kerko.features.results_url_links
KERKO_TEMPLATE_ATOM_FEED
\u2192 kerko.templates.atom_feed
KERKO_TEMPLATE_BASE
\u2192 kerko.templates.base
KERKO_TEMPLATE_ITEM
\u2192 kerko.templates.item
KERKO_TEMPLATE_LAYOUT
\u2192 kerko.templates.layout
KERKO_TEMPLATE_SEARCH
\u2192 kerko.templates.search
KERKO_TEMPLATE_SEARCH_ITEM
\u2192 kerko.templates.search_item
KERKO_TITLE
\u2192 kerko.meta.title
KERKO_USE_TRANSLATIONS
: Remove.KERKO_WHOOSH_LANGUAGE
\u2192 kerko.search.whoosh_language
KERKO_WITH_JQUERY
\u2192 kerko.assets.with_jquery
KERKO_WITH_POPPER
\u2192 kerko.assets.with_popper
KERKO_ZOTERO_API_KEY
\u2192 ZOTERO_API_KEY
KERKO_ZOTERO_BATCH_SIZE
\u2192 kerko.zotero.batch_size
KERKO_ZOTERO_LIBRARY_ID
\u2192 ZOTERO_LIBRARY_ID
KERKO_ZOTERO_LIBRARY_TYPE
\u2192 ZOTERO_LIBRARY_TYPE
KERKO_ZOTERO_LOCALE
\u2192 kerko.zotero.locale
KERKO_ZOTERO_MAX_ATTEMPTS
\u2192 kerko.zotero.max_attempts
KERKO_ZOTERO_WAIT
\u2192 kerko.zotero.wait
KERKOAPP_CHILD_EXCLUDE_RE
\u2192 kerko.zotero.child_exclude_re
KERKOAPP_CHILD_INCLUDE_RE
\u2192 kerko.zotero.child_include_re
KERKOAPP_COLLECTION_FACETS
\u2192 kerko.facets.*
. See sub-parameters type
(set it to \"collection\"
), collection_key
, weight
, and title
.KERKOAPP_EXCLUDE_DEFAULT_BADGES
: Remove. There is no replacement since Kerko does not provide any default badges at this point.KERKOAPP_EXCLUDE_DEFAULT_CITATION_FORMATS
\u2192 kerko.citation_formats.*
. See sub-parameter enable
.KERKOAPP_EXCLUDE_DEFAULT_FACETS
\u2192 kerko.facets.*
. See sub-parameter enable
.KERKOAPP_EXCLUDE_DEFAULT_FIELDS
\u2192 kerko.search_fields.*
. See sub-parameter enable
.KERKOAPP_EXCLUDE_DEFAULT_SCOPES
\u2192 kerko.scopes.*
. See sub-parameter enable
.KERKOAPP_EXCLUDE_DEFAULT_SORTS
\u2192 kerko.sorts.*
. See sub-parameter enable
.KERKOAPP_FACET_INITIAL_LIMIT_LEEWAY
\u2192 kerko.facets.*.initial_limit_leeway
. This is now set individually for each facet, and there is no longer a global parameter.KERKOAPP_FACET_INITIAL_LIMIT
\u2192 kerko.facets.*.initial_limit
. This is now set individually for each facet, and there is no longer a global parameter.KERKOAPP_ITEM_EXCLUDE_RE
\u2192 kerko.zotero.item_exclude_re
KERKOAPP_ITEM_INCLUDE_RE
\u2192 kerko.zotero.item_include_re
KERKOAPP_MIME_TYPES
\u2192 kerko.zotero.attachment_mime_types
KERKOAPP_TAG_EXCLUDE_RE
\u2192 kerko.zotero.tag_exclude_re
KERKOAPP_TAG_INCLUDE_RE
\u2192 kerko.zotero.tag_include_re
PROXY_FIX
\u2192 kerkoapp.proxy_fix.*
kerko.link_groups.navbar
parameter (see the parameters documentation for details).DATA_PATH
nor the INSTANCE_PATH
parameters, then rename KerkoApp's data
directory to instance
.wsgi.app
(or wsgi:app
) instead of kerkoapp.app
(or kerkoapp:app
).Rebuild your search index using the following commands:
flask kerko clean index\nflask kerko sync index\n
Restart the application.
Occurrences of parameter names in custom templates will need to be edited. For example:
config.KERKO_COMPOSER
\u2192 config.kerko_composer
config.KERKO_TITLE
\u2192 config.kerko.meta.title
The following item fields have been renamed. Occurrences of these in your templates will need to be edited:
z_dateAdded
\u2192 date_added
z_dateModified
\u2192 date_modified
The following views have been renamed. Occurrences of these in your templates (perhaps in calls to url_for
) will need to be edited:
item_citation_download
\u2192 item_bib_download
search_citation_download
\u2192 search_bib_download
Configuration initialization and loading has greatly changed. If you have a custom application, it will need to be adapted even if you do not plan to use TOML files. See Creating a custom application for a working example, and refer to the changelog for other breaking changes.
"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Introduction","text":"Kerko is a web application component that provides a user-friendly search and browsing interface for sharing a bibliography managed with the Zotero reference manager.
The combination of Kerko and Zotero gives you the best of both worlds: a rich but easy to use web interface for end-users of the bibliography, and a well-established and powerful bibliographic reference management tool for individuals or teams working on the bibliography's content.
"},{"location":"#how-it-works","title":"How it works","text":"A Kerko-powered bibliography is managed using Zotero, and stored in the cloud on zotero.org, while Kerko itself is incorporated into an application which is installed on a web server. The bibliographic references may reside in a Zotero group library, where multiple users may collaborate to manage the content, or in a Zotero private library. On the web server, Kerko maintains a search index, which is a copy of the Zotero library that is optimized for search. When users interact with the web application, Kerko gets all the required data from that search index, without ever contacting zotero.org. It is through a scheduled task, which runs at regular intervals, that Kerko automatically brings its search index up to date by using the Zotero Web API to retrieve the latest data from zotero.org.
Kerko is implemented in Python using the Flask framework. As an application component, Kerko only works when incorporated into a Flask application. Such an application, KerkoApp, is available for you to use, and can be deployed on a web server. KerkoApp can be seen as just a thin layer over Kerko. It might work for you if you like the default appearance, and if the provided configuration options are sufficient for your needs.
For more advanced needs, you could consider building a custom application, possibly derived from KerkoApp, where additional customizations could be implemented in Python. In this scenario, it is not recommended that you change Kerko itself, but that you use Kerko's Python API to implement your customizations. Kerko is actually a Flask \"blueprint\" (similar to what some other systems might call a plugin or an extension), which allows a modular architecture where the application integrates and extends Kerko, and possibly other blueprints as well; the Kerko-powered bibliography could be just one component of a larger Flask application.
"},{"location":"#demo-site","title":"Demo site","text":"A demo site, which is based on KerkoApp, is available for you to try. You may also view the Zotero library that contains the source data for the demo site.
"},{"location":"#sites-using-kerko","title":"Sites using Kerko","text":"The following sites are powered by Kerko:
Are you using Kerko?
If you would like to add your Kerko-powered site to this list, please e-mail us or submit a pull request.
"},{"location":"#features","title":"Features","text":"The main features provided by Kerko are:
AND
: matches items that contain all specified terms. This is the default relation between terms when no operator is specified, e.g., a b
is the same as a AND b
.OR
: matches items that contain any of the specified terms, e.g., a OR b
.NOT
: excludes items that match the term, e.g., NOT a
.(a OR b) AND c
.\"a b c\"
. The default difference between word positions is 1, meaning that an item will match if it contains the words next to each other, but a different maximum distance may be selected (with the tilde character), e.g. \"web search\"~2
allows up to 1 word between web
and search
, meaning it could match web site search
as well as web search
.faceted^2 search browsing^0.5
specifies that faceted
is twice as important as search
when computing the relevance score of results, while browsing
is half as important. Boosting may be applied to a logical grouping, e.g., (a b)^3 c
.search
, searches
, and searching
all return the same results. The Snowball algorithm is used for that purpose.KerkoApp is a standalone application built around Kerko. It inherits all of Kerko's features and it provides a few additions of its own:
Kerko requires Python 3.8 or later.
Required Python packages will be automatically installed when installing Kerko. The main ones are:
The following front-end resources are loaded from CDNs by Kerko's default templates (but could be completely removed or replaced in custom templates):
Before choosing Kerko for your project, you might want to review the following known limitations of Kerko:
Kerko was inspired by prior work accomplished by Whisky Echo Bravo on two projects:
In 2019, Whisky Echo Bravo was asked to work on another similar project. That made it clear that a general solution would benefit many organizations. However, software from the prior projects had to be rewritten in order to be more adaptable to a variety of needs. That led to Kerko, whose initial development was made possible through the following project:
Since then, Kerko has continued to evolve, thanks to work by Whisky Echo Bravo and other contributors, often through funding provided by organizations needing new features or customizations of Kerko.
"},{"location":"about/#design-choices","title":"Design choices","text":"Here are some of the design choices that have guided the development of Kerko so far:
The name Zotero reportedly derives from the Albanian word zot\u00ebroj, which means \"to learn something extremely well, that is to master or acquire a skill in learning\" (Source: Mark Dingemanse, 2008, Etymology of Zotero).
The name Kerko is a nod to Zotero as it takes a similar etymological route: it derives from the Albanian word k\u00ebrkoj, which means \"to ask, to request, to seek, to look for, to demand, to search\" and seems fit to describe a search tool.
"},{"location":"changelog/","title":"Changelog","text":"Before doing an upgrade, please check the \"How to upgrade\" section of the Kerko documentation.
"},{"location":"changelog/#120-2024-08-03","title":"1.2.0 (2024-08-03)","text":"New features:
kerko.facets.language.enabled
configuration parameter to true
. By default, Kerko will try to normalize the language names to make the facet more usable; see kerko.facets.language.
in the configuration parameters documentation for details.Removed features:
setup.py
have been removed. Equivalent pybabel
commands can be used instead (see the updated Localization section of the documentation).Other changes:
kerko.facets.item_type.initial_limit
, now 10
instead of 0
.kerko.facets.item_type.initial_limit_leeway
, now 4
instead of 2
.kerko.facets.link.initial_limit_leeway
, now 0
instead of 2
.kerko.facets.tag.initial_limit
, now 10
instead of 0
.kerko.facets.tag.initial_limit_leeway
, now 4
instead of 2
.kerko.facets.year.initial_limit_leeway
, now 0
instead of 2
.setup.cfg
to pyproject.toml
.pip
do not mistake a development version for a previously published version. Version numbers are now extracted from the tags and revisions of the Git repository.Deprecated APIs:
kerko.TRANSLATION_DIRECTORIES
is deprecated and will be removed in Kerko 2.x. The variable kerko.TRANSLATION_DIRECTORY
should be used instead, and its type is a string instead of a list. If you are using a custom application, please adapt it accordingly (you may check KerkoApp's __init__.py
for an example).Features:
kerko.scopes.pubyear.enabled
configuration parameter to false
.kerko.pages.*.
for defining content pages whose content come from selected Zotero standalone notes.\"page\"
type for the kerko.link_groups.*.
configuration table, to allow the creation of links to content pages.kerko.performance.whoosh_index_memory_limit
and kerko.performance.whoosh_index_processors
to give some control over the Whoosh search engine's indexing performance.Bug fixes:
caseName
search field.kerko.features.print_results_max_count
is greater than zero.Other changes:
rel=\"noopener\"
to target=\"_blank\"
links.rel=\"noreferrer\"
to links derived from Zotero library data, e.g., user-provided URLs, DOIs, link attachments.kerko.performance.whoosh_index_memory_limit
parameter.page-len=1
URL parameter. This is achieved through removal of the id
parameter from pagination URLs. Obtaining those ids was requiring extra processing. Instead, the id
parameter is now added through the browser History API when a pagination link is visited.Backwards incompatible changes:
Possibly backwards incompatible changes (more or less internal API changes):
kerko.blueprint
global object. Applications must now instantiate the blueprint by calling kerko.make_blueprint()
before registering it. This prevents attempts to mutate the object after its registration, especially in tests.kerko.extractors.TransformerExtractor
no longer applies transformers on None
values. If you need a transformer to process a None
value (Kerko itself has no such transformer), you now have to set the new skip_none_value
argument to False
when instantiating the extractor.Features:
kerko.features.download_item
.Bug fixes:
errno.EINTR
error code). Not an issue anyone should have encountered!Backwards incompatible changes:
kerko.features.download_results_link
\u2192 kerko.features.download_results
.kerko.features.print_item_link
\u2192 kerko.features.print_item
kerko.features.print_results_link
\u2192 kerko.features.print_results
Other changes:
Features:
kerko.link_groups.*.
for defining sets of links that may be used for navigation.kerko.breadcrumb
and kerko.link_groups.breadcrumb_base
).Bug fixes:
kerko.zotero.csl_style
configuration parameter.Backwards incompatible changes:
kerko.link_groups.navbar
configuration. There is no default translation for it. To change the default text or to translate it, you must override the default kerko.link_groups.navbar
in your configuration file. If you have overridden the _navbar_items.html.jinja2
template and wish to use the configuration, you might want to adapt it, or revert to the default template.Other changes:
Features:
--full
option to the sync
command line interface (CLI) command.Bug fixes:
kerko.facets.*.collection_key
configuration parameter.kerko.features.download_results_max_count
and kerko.features.print_results_max_count
configuration parameters.Other changes:
Rename the default branch of the repository from 'master' to 'main'. If you have cloned the repository with Git, use the following commands to rename your local branch:
git branch -m master main\ngit fetch origin\ngit branch -u origin/main main\ngit remote set-head origin -a\n
Make the config
CLI command show the configuration in TOML format.
config
CLI command hide secrets by default. Add a --show-secrets
option.Backwards incompatible changes:
clean
CLI command from cleaning everything by default. To delete everything, you now have to run flask kerko clean everything
. This may help prevent accidental deletion of the cache, which in some instances can take long to rebuild.kerko.citation_formats.*
\u2192 kerko.bib_formats.*
.kerko.features.download_citations_link
\u2192 kerko.features.download_results_link
kerko.features.download_citations_max_count
\u2192 kerko.features.download_results_max_count
kerko.features.print_citations_link
\u2192 kerko.features.print_results_link
kerko.features.print_citations_max_count
\u2192 kerko.features.print_results_max_count
item_citation_download
\u2192 item_bib_download
search_citation_download
\u2192 search_bib_download
Warning: Upgrading from version 0.9 or earlier will require that you adapt your installation and configuration files, then rebuild your search index. Use the commands below, then restart the application. If you are using KerkoApp, make sure to check its changelog.
flask kerko clean index\nflask kerko sync index\n
Features:
kerko.features.open_in_zotero_app
and kerko.features.open_in_zotero_web
). Even when these are enabled, a user who wishes to use such button must first enable it from the (also new) Preferences dialog.kerko config
command to the Flask command line interface for displaying all configuration parameters.Other changes:
Backwards incompatible changes:
DATA_PATH
and INSTANCE_PATH
configuration parameters. You may need to set one or both of those parameters, and/or move your existing data directory.kerko.config_helpers.config_set()
function. Here is a mapping of the changed parameters:KERKO_BOOTSTRAP_VERSION
\u2192 kerko.assets.bootstrap_version
KERKO_CSL_STYLE
\u2192 kerko.zotero.csl_style
KERKO_COMPOSER
\u2192 kerko_composer
KERKO_DATA_DIR
\u2192 DATA_PATH
. Now optional, relative to the instance path, and defaulting to kerko
instead of data/kerko
.KERKO_DOWNLOAD_ATTACHMENT_NEW_WINDOW
\u2192 kerko.features.download_attachment_new_window
KERKO_DOWNLOAD_CITATIONS_LINK
\u2192 kerko.features.download_citations_link
KERKO_DOWNLOAD_CITATIONS_MAX_COUNT
\u2192 kerko.features.download_citations_max_count
KERKO_FEEDS
\u2192 kerko.feeds.formats
KERKO_FEEDS_FIELDS
\u2192 kerko.feeds.fields
KERKO_FEEDS_MAX_DAYS
\u2192 kerko.feeds.max_days
KERKO_FEEDS_REJECT_ANY
\u2192 kerko.feeds.reject_any
KERKO_FEEDS_REQUIRE_ANY
\u2192 kerko.feeds.require_any
KERKO_FULLTEXT_SEARCH
\u2192 kerko.search.fulltext
KERKO_HIGHWIREPRESS_TAGS
\u2192 kerko.meta.highwirepress_tags
KERKO_JQUERY_VERSION
\u2192 kerko.assets.jquery_version
KERKO_PAGE_LEN
\u2192 kerko.pagination.page_len
KERKO_PAGER_LINKS
\u2192 kerko.pagination.pager_links
KERKO_POPPER_VERSION
\u2192 kerko.assets.popper_version
KERKO_PRINT_CITATIONS_LINK
\u2192 kerko.features.print_citations_link
KERKO_PRINT_CITATIONS_MAX_COUNT
\u2192 kerko.features.print_citations_max_count
KERKO_PRINT_ITEM_LINK
\u2192 kerko.features.print_item_link
KERKO_RELATIONS_INITIAL_LIMIT
\u2192 kerko.features.relations_initial_limit
KERKO_RELATIONS_LINKS
\u2192 kerko.features.relations_links
KERKO_RELATIONS_SORT
\u2192 kerko.features.relations_sort
KERKO_RESULTS_ABSTRACTS_MAX_LENGTH
\u2192 kerko.features.results_abstracts_max_length
KERKO_RESULTS_ABSTRACTS_MAX_LENGTH_LEEWAY
\u2192 kerko.features.results_abstracts_max_length_leeway
KERKO_RESULTS_ABSTRACTS
\u2192 kerko.features.results_abstracts
KERKO_RESULTS_ABSTRACTS_TOGGLER
\u2192 kerko.features.results_abstracts_toggler
KERKO_RESULTS_ATTACHMENT_LINKS
\u2192 kerko.features.results_attachment_links
KERKO_RESULTS_FIELDS
\u2192 kerko.search.result_fields
KERKO_RESULTS_URL_LINKS
\u2192 kerko.features.results_url_links
KERKO_TEMPLATE_ATOM_FEED
\u2192 kerko.templates.atom_feed
KERKO_TEMPLATE_BASE
\u2192 kerko.templates.base
KERKO_TEMPLATE_ITEM
\u2192 kerko.templates.item
KERKO_TEMPLATE_LAYOUT
\u2192 kerko.templates.layout
KERKO_TEMPLATE_SEARCH
\u2192 kerko.templates.search
KERKO_TEMPLATE_SEARCH_ITEM
\u2192 kerko.templates.search_item
KERKO_TITLE
\u2192 kerko.meta.title
KERKO_WHOOSH_LANGUAGE
\u2192 kerko.search.whoosh_language
KERKO_WITH_JQUERY
\u2192 kerko.assets.with_jquery
KERKO_WITH_POPPER
\u2192 kerko.assets.with_popper
KERKO_ZOTERO_API_KEY
\u2192 ZOTERO_API_KEY
KERKO_ZOTERO_BATCH_SIZE
\u2192 kerko.zotero.batch_size
KERKO_ZOTERO_LIBRARY_ID
\u2192 ZOTERO_LIBRARY_ID
KERKO_ZOTERO_LIBRARY_TYPE
\u2192 ZOTERO_LIBRARY_TYPE
KERKO_ZOTERO_LOCALE
\u2192 kerko.zotero.locale
KERKO_ZOTERO_MAX_ATTEMPTS
\u2192 kerko.zotero.max_attempts
KERKO_ZOTERO_WAIT
\u2192 kerko.zotero.wait
kerko.config_helpers.config_update(app.config, kerko.DEFAULTS)
.Composer.__init__()
now only takes a configuration object as argument instead of a bunch of arguments. Thus, the initial values of the Composer
instance now depend solely on the configuration.KERKO_USE_TRANSLATIONS
configuration variable. Kerko now relies on the application's default Babel domain and translation directories. Custom applications that wish to load Kerko's translations should now add kerko.TRANSLATION_DOMAIN
and kerko.TRANSLATION_DIRECTORIES
to their Babel configuration.__init__()
method of FacetSpec
and its subclasses now only accept keyword arguments.sort_key
argument to FacetSpec.__init__()
is now sort_by
.Composer
built-in fields z_dateAdded
and z_dateModified
are now named date_added
and date_modified
respectively.Warning: Upgrading from version 0.8.x or earlier will require that you rebuild your search index. Use the following commands, then restart the application:
flask kerko clean index\nflask kerko sync index\n
Features:
kerko count
CLI command (mostly meant for development purposes).Bug fixes:
KERKO_PRINT_CITATIONS_LINK
and KERKO_DOWNLOAD_CITATIONS_LINK
are both set to False
.kerko sync
CLI command not returning an error code with some types of failures.Other changes:
page
parameter from pagination links when page=1
.pyproject.toml
.Backwards incompatible changes:
KERKO_FACET_COLLAPSING
option. The new initial limit on facets values made this feature largely redundant.collapsible
param from the FacetSpec
class.KERKO_ZOTERO_START
and KERKO_ZOTERO_END
(were only used for development and no longer practical).Changes that might break custom themes:
facet
, facet_item
, facet_items
, facet_fields
template macros have changed.facets-container
, facets
, and facets-modal-body
element ids are now required in search.html.jinja2
.Possibly backwards incompatible changes (more or less internal API changes):
criteria
module. Criteria.keywords
and Criteria.filters
work pretty much as before, but everything else has changed.query
module, which had organically grown into an tangled mess, now replaced with the searcher
module. This new API is completely different.searcher
API.views
module into multiple modules under views
(item_creators
, item_facets
, item_relations
, routes
, search
), and moved breadbox
, meta
(as item_meta
), pager
, and sorter
under views
.Bug fixes:
Warning: Upgrading from version 0.7.x or earlier will require that you clean and re-sync your existing search index. Use the following commands, then restart the application:
flask kerko clean index\nflask kerko sync\n
Features:
KERKO_FULLTEXT_SEARCH
to False
. Since this feature relies on Zotero's full-text indexing, you must make sure that it works in Zotero first; see Zotero's documentation.KERKO_RESULTS_URL_LINKS
to False
.KERKO_RESULTS_ATTACHMENT_LINKS
to False
.standalone_attachment_download
, lets one retrieve a standalone file attachment.KERKO_RESULTS_ABSTRACTS_MAX_LENGTH
and KERKO_RESULTS_ABSTRACTS_MAX_LENGTH_LEEWAY
).KERKO_HIGHWIREPRESS_TAGS
to False
.href
attribute of <a>
elements.Bug fixes:
Other changes:
sync cache
command to the command line interface.sortable
Whoosh flag on relevant fields._
) are now trimmed from facet value labels. This happens after sorting the values, which means that the underscore can still be used as a prefix to alter the alphabetical order.type
HTML attribute to record download links.rel=\"alternate\"
HTML attribute to record download links on item pages. Also add a corresponding link
element to the page head
.Backwards incompatible changes:
kerko index
CLI command (use kerko sync
instead).Possibly backwards incompatible changes (more or less internal API changes):
KERKO_RESULTS_FIELDS
setting now includes the 'url'
field. If you have overridden that setting in your application and KERKO_RESULTS_URL_LINKS
is enabled, you'll probably have to add 'url'
too.item_type
has been renamed to item_type_label
. If you have custom templates, please review any use of item.item_type
.kerko/_search-result.html.jinja2
template has changed somewhat. If you have overridden it, you'll need to review the changes.ItemContext
class has been eliminated. The Extractor.extract()
method now receives an item's dictionary instead of an ItemContext
object, and if an item has children these are now available directly in the item (with the children
key). If you have created custom extractor classes, their extract()
method will need to be adapted accordingly.BaseAttachmentsExtractor
\u2192 BaseChildAttachmentsExtractor
BaseNotesExtractor
\u2192 BaseChildNotesExtractor
LinkedURIAttachmentsExtractor
\u2192 ChildLinkedURIAttachmentsExtractor
NotesTextExtractor
\u2192 ChildNotesTextExtractor
RawNotesExtractor
\u2192 RawChildNotesExtractor
RelationsInNotesExtractor
\u2192 RelationsInChildNotesExtractor
StoredFileAttachmentsExtractor
\u2192 ChildFileAttachmentsExtractor
item_attachment_download
\u2192 child_attachment_download
alternateId
\u2192 alternate_id
Security fixes:
Bug fixes:
Other changes:
Documentation changes:
Warning: Upgrading from version 0.6 or earlier will require that you clean and re-sync your existing search index. Use the following commands, then restart the application:
flask kerko clean index\nflask kerko sync\n
Features:
_cites
tag.dc.replaces
relation that's managed internally by Zotero on some operations such as item merges.id
parameter to the search result URLs, and redirect the user to that item's permanent URL if the search result no longer matches because of database changes.search
to the search form.aria-label
attribute to many elements.aria-current
attribute to indicate the current value of widgets.Bug fixes:
Other changes:
setup.py
to setup.cfg
.src
layout.Backwards incompatible changes:
pager
dict passed to the _pager.html.jinja2
template are now lists. Previously, only the values at keys 'before'
and 'after'
were lists; now the values at keys 'previous'
, 'first'
, 'current'
, 'last'
, and 'next'
are lists as well.'blacklist'
and 'whitelist'
in variable names are replaced with 'exclude'
and 'include'
.KERKO_RESULTS_ABSTRACT
configuration variable is replaced by two variables, KERKO_RESULTS_ABSTRACTS
(note the now plural form) and KERKO_RESULTS_ABSTRACTS_TOGGLER
.{url_prefix}/{itemID}/export/{format}
for individual items ('export'
has been inserted), and {url_prefix}/export/{format}/
for search result pages ('download'
has been replaced by 'export'
).Extractor
class' interface has changed, improving consistency and separation of concerns:__init__()
must now be specified as keyword arguments.extract()
method no longer have a document
argument, and the spec
argument is now the last one. The method now returns a value instead of assigning it to the document.extract_and_store()
method handles extraction, encoding, and assignment to the document, assigning the value only when it is not None
.AttachmentsExtractor
class has been renamed to StoredFileAttachmentsExtractor
.InCollectionExtractor
now extends collection membership to subcollections. To preserve the previous behavior, set the check_subcollections
parameter to False
when initializing the extractor.Possibly backwards incompatible changes (more or less internal API changes):
search_results
variable passed to the search.html.jinja2
template is now an iterator of tuples, where the first element of each tuple is a result, and the second element the URL of the result.Security fixes:
Backwards incompatible changes:
KERKO_DATA_DIR
configuration variable. KerkoApp users don't need to worry about this as KerkoApp takes care of it, but custom apps that did not already set this variable now have to.Features:
KERKO_DOWNLOAD_ATTACHMENT_NEW_WINDOW
configuration variable to control whether to open documents in a new window or in the same window.Bug fixes:
Other changes:
Possibly backwards incompatible changes (more or less internal API changes):
content_with_badges
template macro as badges
, and leave it to the caller to display content.Warning: Upgrading from version 0.4 or earlier will require that you clean and re-sync your existing search index. Use the following commands:
flask kerko clean index\nflask kerko sync\n
Features:
KERKO_TEMPLATE_*
configuration variables for page template names.renderer
argument to kerko.specs.FacetSpec
, kerko.specs.BadgeSpec
).KERKO_RESULTS_FIELDS
configuration variable to specify which fields to retrieve with search queries.kerko.extractors.InCollectionExtractor
, new parameters for kerko.codecs.BooleanFacetCodec
).Bug fixes:
Other changes:
kerko index
in favor of new command kerko sync
.Possibly backwards incompatible changes (more or less internal API changes):
kerko.composer.Composer.__init__()
.kerko.composer.Composer.__init__()
arguments default_note_whitelist_re
as default_child_whitelist_re
, default_note_blacklist_re
as default_child_blacklist_re
.kerko.views.item()
as kerko.views.item_view()
._facet.html.jinja2
as _facets.html.jinja2
.checkboxes
in template macro field()
with add_link_icon
and remove_link_icon
.Features:
faceted^2 search browsing^0.5
.Security fixes:
Other changes:
AndNot
, AndMaybe
, Require
were unwanted but enabled by default by Whoosh's OperatorsPlugin
).Features:
Bug fixes:
Other changes:
Possibly backwards incompatible changes (more or less internal API changes):
kerko.composer.Composer.get_ordered_specs()
replaces get_ordered_scopes()
, get_ordered_facets()
and get_ordered_sorts()
.In this section, we will assume that you are using Kerko through KerkoApp. Some elements may not apply if you have integrated Kerko into your own custom Flask application (see Configuration in custom applications).
"},{"location":"config-basics/#parameter-styles","title":"Parameter styles","text":"When looking at Kerko configuration options, you will quickly notice two styles of parameter names, uppercase names and lowercase names.
Uppercase names, such as SECRET_KEY
, ZOTERO_LIBRARY_ID
, DATA_PATH
, BABEL_DEFAULT_LOCALE
, follow the usual convention for environment variables. Most Flask and Flask extensions parameter names follow this convention. Some Kerko parameters have uppercase names too, but only those parameters that may usefully be set as environment variables. Internally, those parameters are stored into a flat Python dictionary.
Most of Kerko parameters use lowercase names. They are also organized into a hierarchy, and are usually referenced using dot-separated paths. Examples are: kerko.features.results_abstracts
, kerko.meta.title
, kerko.facets.item_type.enabled
. Internally, those parameters are stored into nested Python dictionaries.
Documentation convention
In this manual, we will generally refer to a hierarchical parameter using its full dot-separated path, for example kerko.meta.title
, except when context makes repeating the full path redundant.
KerkoApp provides two ways to set configuration parameters:
The above list is in ascending order of precedence. This means that a given parameter set in a TOML file can be overridden by an environment variable.
We do not recommend configuring the same parameter in multiple places, as that might confuse systems administrators, but a layered approach is useful in implementing the Twelve-factor App methodology.
TOML files are the preferred and most convenient way of configuring KerkoApp. Environment variables, however, are still supported, as some parameters cannot be set in TOML files, such as FLASK_APP
and KERKOAPP_CONFIG_FILES
.
The TOML syntax allows organizing parameters under headers to avoid repetition and to make the file more readable. Therefore, two following two examples are equivalent ways of setting the kerko.meta.title
parameter:
kerko.meta.title = \"My Awesome Bibliography\"\n
TOML example 2[kerko.meta]\ntitle = \"My Awesome Bibliography\"\n
Note that if headers are used in a TOML file, any top-level parameter must be set above the first header:
Correct TOML exampleZOTERO_LIBRARY_ID = \"123456\"\n\n[kerko.meta]\ntitle = \"My Awesome Bibliography\"\n
Incorrect TOML example[kerko.meta]\ntitle = \"My Awesome Bibliography\"\n\nZOTERO_LIBRARY_ID = \"123456\"\n
By default, KerkoApp will look for a series of TOML files:
config.toml
instance.toml
.secrets.toml
For each of those, KerkoApp first looks for the file into the current working directory. If it does not find it there, it searches by traversing directories upwards until it finds the file or reaches the root directory. At this point, if the file is still not found, the same scanning process is reapplied, but this time starting from the instance path. After that, whether the file was found or not, KerkoApp continues with the next filename in the list.
The files are loaded in the specified order. The parameters from each file get merged into the previously known configuration. If a given parameter was already set, its value is overwritten by the one from the later file.
This approach allows a layered configuration where:
config.toml
contains general (public) parameters. It is safe (and wise) to manage this file in a code repository.instance.toml
contains server-specific parameters such as those that might refer to paths or systems that only exist on the server. This file is usually not put into a code repository..secrets.toml
contains secrets (private parameters) that ought to be known only to the server, such as API keys. This file should never be added to a code repository.You do not have to use all three files. One might, for example, use just config.toml
and .secrets.toml
, and not create instance.toml
.
You may replace the default list of TOML file paths by setting the KERKOAPP_CONFIG_FILES
environment variable.
In the example below, the default list of TOML files is replaced by a list of two file paths, one relative and the other absolute:
POSIXWindowsKERKOAPP_CONFIG_FILES=\"first_config.toml;/absolute/path/to/second_config.toml\"\n
KERKOAPP_CONFIG_FILES=\"first_config.toml;C:\\absolute\\path\\to\\second_config.toml\"\n
"},{"location":"config-basics/#environment-variables","title":"Environment variables","text":"KerkoApp requires environment variable names to be prefixed with KERKOAPP_
. The SECRET_KEY
parameter, for example, becomes KERKOAPP_SECRET_KEY
when specified as an environment variable.
For hierarchical parameters, each dot separator (.
) must be replaced by two underscore characters (__
). The kerko.meta.title
parameter, for example, becomes KERKOAPP_kerko__meta__title
when specified as an environment variable. Such conversion is not necessary in TOML files.
Note that Windows does not allow lowercase environment variable names. Consequently, Windows users have no choice but to set lowercase parameters in TOML files.
Environment variables may be set from various locations, in the following order (refer to the Flask documentation for more details):
.flaskenv
file..env
file.--env-file
command line option.The above list is in ascending order of precedence. This means that a given parameter set earlier can be overridden later as values get loaded. Files are located by scanning directories upwards from the directory you call flask from.
"},{"location":"config-basics/#configuration-in-custom-applications","title":"Configuration in custom applications","text":"If you are using a custom Flask application instead of KerkoApp, some of the present documentation may not fully apply to you. For example:
KERKOAPP_
, or no prefix at all.In a custom application, hierarchical parameters may be set in Python using the API provided by Kerko, as in the following example:
Setting a configuration parameter in Pythonfrom kerko.config_helpers import config_set\nconfig_set(app.config, \"kerko.meta.title\", \"My Awesome Bibliography\")\n
Such assignments must be done during the initialization process. The application cannot change a setting while responding to a request.
"},{"location":"config-basics/#viewing-the-configuration","title":"Viewing the configuration","text":"With configuration parameters potentially taking values from different sources (default values, configuration files, environment variables), you may sometimes want to verify the actual values taken by each parameter.
The following command will show the configuration parameters of the application and their values:
flask kerko config\n
"},{"location":"config-guides/","title":"Configuration guides","text":"This sections provides guidance on configuring specific aspects of Kerko.
"},{"location":"config-guides/#defining-custom-facets-based-on-zotero-collections","title":"Defining custom facets based on Zotero collections","text":"Zotero collections can be mapped to custom facets in Kerko. With this scheme, a collection in the Zotero library represents a facet, and its subcollections correspond to values (or user-selectable filters) within the facet. Figure 1 below illustrates such mapping, taken from the demo library and its corresponding demo site.
Figure 1. Side-by-side comparison between the structure of collections in a Zotero library and the resulting faceted browsing interface in Kerko.For such mapping to work, the following conditions must be met:
Once your Zotero library it set up to meet those conditions, you may configure the facets. For the example in Figure 1, the configuration looks like this:
[kerko.facets.topic]\nenabled = true\ntype = \"collection\"\ncollection_key = \"KY3BNA6T\"\nfilter_key = \"topic\"\ntitle = \"Topic\"\nweight = 110\ninitial_limit = 5\ninitial_limit_leeway = 2\n\n[kerko.facets.field_of_study]\nenabled = true\ntype = \"collection\"\ncollection_key = \"7H2Q7L6I\"\nfilter_key = \"field-of-study\"\ntitle = \"Field of study\"\nweight = 120\ninitial_limit = 5\ninitial_limit_leeway = 2\n\n[kerko.facets.contribution]\nenabled = true\ntype = \"collection\"\ncollection_key = \"JFQRH4X2\"\nfilter_key = \"contribution\"\ntitle = \"Contribution\"\nweight = 130\ninitial_limit = 5\ninitial_limit_leeway = 2\n
For details on each parameter, please refer to the parameters documentation. However, we can highlight some elements:
collection_key
is the key assigned by Zotero to identify the collection. An easy way to find this key is to visit your library using Zotero's web interface. Click the collection, and check its URL in your browser's address bar. In our example, the URL of the \"Topic\" collection is https://www.zotero.org/groups/2348869/kerko_demo/collections/KY3BNA6T, hence the use of \"KY3BNA6T\"
as the collection key.filter_key
tells Kerko the key to use in URLs when a user of your Kerko site selects a filter within the facet. In our example, for the \"Topic\" facet we chose to set this parameter to \"topic\"
and, consequently, the search URL will look like https://demo.kerko.whiskyechobravo.com/bibliography/?topic=Z8LT6QZG.2ZGZH2E2.title
is the heading that Kerko will show for the facet. If desired, you may choose a title that is different from the collection's name in Zotero.weight
determines the relative position of the facet. Small numbers (low weights) rise above large ones (heavier weights). This explains why, in our example, Kerko displays \"Topic\" (weighting 110) above \"Field of study\" (120) and \"Contribution\" (130).Other things to know:
After adding a new facet, you must clean and re-sync the search index. Please check the documentation on synchronization, but in short you have to use the following commands:
flask kerko clean index\nflask kerko sync index\n
Kerko allows a facet to have any number of hierarchical sublevels (nested subcollections).
Phew! We think that this is simpler to setup in practice than it looks in writing. Hopefully you will agree.
"},{"location":"config-guides/#creating-custom-content-pages-based-on-zotero-standalone-notes","title":"Creating custom content pages based on Zotero standalone notes","text":"If you wish to provide informational pages along with your bibliography, you can add standalone notes to your Zotero library, and configure Kerko to provide pages whose content will come from those notes.
Say you want to provide \"About\" and \"Contact Us\" pages with simple text content, you could implement them by following these steps:
\"Y48RBWDB\"
is the item ID.Define the \"About\" and \"Contact Us\" pages by adding the following snippet to your Kerko configuration:
[kerko.pages.about]\npath = \"/about\"\nitem_id = \"Y48RBWDB\"\ntitle = \"About\"\n\n[kerko.pages.contact_us]\npath = \"/contact\"\nitem_id = \"REG3CL25\"\ntitle = \"Contact Us\"\n
... where:
path
is the desired URL path for the page;item_id
is the note's item ID (as found earlier);title
is the desired title for the page in the Kerko site.For more details on each parameter, please refer to the parameters documentation.
Then, you will probably want the navigation bar to provide links to your pages. The following configuration code defines a navigation bar with three links \u2014 a link to the bibliography, and links to the \"About\" and \"Contact Us\" pages:
[[kerko.link_groups.navbar]]\ntype = \"endpoint\"\nendpoint = \"kerko.search\"\ntext = \"Bibliography\"\n\n[[kerko.link_groups.navbar]]\ntype = \"page\"\npage = \"about\"\ntext = \"About\"\n\n[[kerko.link_groups.navbar]]\ntype = \"page\"\npage = \"contact_us\"\ntext = \"Contact Us\"\n
... where:
type
parameter indicates the type of link (\"endpoint\"
indicates a core Kerko link, while \"page\"
indicates a link to a page defined under kerko.pages.*
);page
parameter specifies the target of the link, e.g., the unique key of the page (which replaces the *
in the kerko.pages.*
header);text
parameter provides the link's text to show in the navigation bar.Navigation bar links will be displayed in the order they appear in the configuration file.
For more details on this configuration section, please refer to the parameters documentation
Make sure Kerko's database is up-to-date with your new note by running the following command:
flask kerko sync\n
Restart your Kerko application to load the configuration changes. If all goes well, you will have new \"About\" and \"Contact Us\" pages accessible from the navigation bar.
Please note that Kerko does not restructure the HTML that Zotero generates for notes. If you use headings in your notes, we recommend that you start with the \"Heading 2\" heading level, because \"Heading 1\" should be reserved to Kerko (for the page title).
Kerko is not, and never will be, a web content management system. Its sole purpose is to provide a nice interface for a Zotero library. Thus, Kerko content pages are just a very rudimentary way of providing simple informational content along with the library. For more advanced content needs, you might have to consider integrating Kerko into a custom Flask application backed with proper content editing features.
"},{"location":"config-guides/#ensuring-full-text-indexing-of-your-attachments-in-zotero","title":"Ensuring full-text indexing of your attachments in Zotero","text":"Kerko's full-text indexing relies on text content extracted from attachments by Zotero. Consequently, for Kerko's full-text search to work, you must make sure that full-text indexing works in Zotero first; see Zotero's documentation on full-text indexing.
Individual attachments in Zotero can be indexed, partially indexed, or unindexed. Various conditions may cause an attachment to be partially indexed or unindexed, e.g., file is large, has not been processed yet, or does not contain text.
Zotero shows the indexing status in the attachment's right pane. If it shows \"Indexed: Yes\", all is good. If it shows \"Indexed: No\" or \"Indexed: Partial\", then clicking the \"Reindex Item\" button (next to the indexing status) should ensure that the attachment gets fully indexed, that is if the file actually contains text. If there is no \"Reindex Item\" button, it probably means that Zotero does not support that file type for full-text indexing (at the moment, it only supports PDF and plain text files).
It can be tedious to go through hundreds of attachments just to find out whether they are indexed or not. To make things easier, you could create a saved search in your Zotero library to get an always up-to-date list of unindexed PDFs. Use the following search conditions:
This search might return a long list of unindexed attachments. To reindex them all at once, you may select them, then right-click to get the contextual menu, and select \"Reindex items\". It may require some time to update your library on zotero.org. Note that documents that have no text content, as well as missing documents, will still be considered as unindexed and appear in the results of the saved search.
Controlling the indexing status will not only improve full-text search on your Kerko site, but also full-text search from within Zotero!
"},{"location":"config-guides/#providing-cites-and-cited-by-relations","title":"Providing Cites and Cited by relations","text":"Zotero allows one to link items together through its Related field. However, such relations are not typed nor directed, making it impossible (1) to indicate the nature of the relation, or (2) to distinguish which of two related items is the citing entity, and which is the one being cited. Consequently, Kerko has its own method for setting up those relations.
To establish Cites relations in your Zotero library, you must follow the procedure below:
https://www.zotero.org/groups/9999999/items/ABCDEFGH
or https://www.zotero.org/users/9999999/items/ABCDEFGH
._cites
. That tag that will tell Kerko that this particular note is special, that it contains relations.At the next synchronization, Kerko will retrieve the references found in notes tagged with _cites
. Afterwards, proper hyperlinked citations will appear in the Cites and Cited by sections of the related bibliographic records.
Remarks:
zotero://select/
) in the notes, if you prefer those to Zotero URIs.href
attribute of <a>
elements.This section describes most configuration parameters available to Kerko and KerkoApp.
Unless indicated otherwise, all parameters are optional and will take a default value if omitted from your configuration.
Note
Flask and Flask extensions loaded by the application may provide additional configuration parameters that are not described in this manual. To find those, please refer to the documentation of the relevant package.
Changing the Kerko configuration can be disruptive
Making any change to a Kerko configuration file requires that you at least restart the application afterwards for the change to become effective.
Moreover, some parameters have an effect on the structure of the cache or the search index that Kerko depends on. Changing this kind of parameter may require that you rebuild either. Refer to the documentation of the parameter to check if specific actions need to be taken after a change.
Prefix your environment variables
KerkoApp users must prefix parameter names with KERKOAPP_
when configuring them as environment variables. However, that prefix should be omitted when the same parameter is set in a TOML file. See environment variables for details.
Be a minimalist, only set a parameter when necessary
If a parameter's default value works for you, just omit that parameter from your configuration file. Your configuration file will be much smaller and easier to read, and you will have less things to check when eventually upgrading Kerko.
"},{"location":"config-params/#babel_default_locale","title":"BABEL_DEFAULT_LOCALE
","text":"The default language of the user interface.
Type: String Default value: \"en\"
BABEL_DEFAULT_TIMEZONE
","text":"The timezone to use for user facing times. Any timezone name supported by the pytz package should work.
Type: String Default value: \"UTC\"
CONFIG_FILES
","text":"Specifies where to look for one or more TOML configuration files. The value must be a semicolon-separated list of file paths.
The files are loaded in the specified order. The parameters from each file get merged into the previously known configuration. If a given parameter was already set, its value is overwritten by the one from the later file.
Paths may be absolute or relative. Relative paths are resolved from the current working directory. If a specified file is not found there, it is searched by traversing the directories upwards. If the root directory is reached and the file is still not found, then the same search method is reapplied, but this time starting from the INSTANCE_PATH
.
Type: String Default value: \"config.toml;instance.toml;.secrets.toml\"
Environment variable only
This parameter is specific to KerkoApp and cannot be set in a TOML file. It can only be set as an environment variable, therefore it should actually be referenced as KERKOAPP_CONFIG_FILES
. See environment variables for details.
DATA_PATH
","text":"The data path specifies a directory where Kerko may store its cache, search index, and file attachments. This may be provided as an absolute path or as a relative path. If a relative path is given, it will be relative to INSTANCE_PATH
.
Type: String Default value: \"kerko\"
INSTANCE_PATH
","text":"The instance path specifies a directory where the application may store data and configuration files.
Type: String Default value: Determined by Flask. In practice, the default for KerkoApp users is a directory named instance
located at the same level as the wsgi.py
file. You may set INSTANCE_PATH
to a different directory, which you must specify as an absolute path.
Environment variable only
This parameter is specific to KerkoApp and cannot be set in a TOML file. It can only be set as an environment variable, therefore it should actually be referenced as KERKOAPP_INSTANCE_PATH
. See environment variables for details.
LOGGING_ADDRESS
","text":"Address to send log messages to. Used only if LOGGING_HANDLER
is set to \"syslog\"
.
Type: String Default value: \"/dev/log\"
LOGGING_FORMAT
","text":"Log message format string, with %-style placeholders. Refer to the Python logging documentation for allowed attributes.
Type: String Default value: \"[%(asctime)s] %(levelname)s in %(module)s: %(message)s\"
LOGGING_HANDLER
","text":"Logging handler to use. At this time, the sole allowed value is \"syslog\"
. If no value is set, the default handler will write to the default stream (usually sys.stderr
).
Type: String
"},{"location":"config-params/#logging_level","title":"LOGGING_LEVEL
","text":"Severity of events to log. Allowed values are \"DEBUG\"
, \"INFO\"
, \"WARNING\"
, \"ERROR\"
, and \"CRITICAL\"
.
Type: String Default value: \"DEBUG\"
if the application is running in debug mode, or \"WARNING\"
otherwise.
SECRET_KEY
","text":"This parameter is required for generating secure tokens in web forms. It should have a hard to guess value, and should really remain secret.
This parameter is required and has no default value.
Type: String
"},{"location":"config-params/#zotero_api_key","title":"ZOTERO_API_KEY
","text":"This parameter specifies your Zotero API key, as created on zotero.org.
Kerko does not need to write to your library. Thus, we recommend that your API key be read-only, and that it does not grant any more access to your Zotero data than strictly necessary.
On zotero.org, the API key creation options vary on whether you want to connect Kerko to a personal library or to a group library:
Personal libraryGroup libraryMake sure to check Allow library access, as well as Allow notes access, unless you are certain you won't need any Kerko feature that relies on notes. If you are unsure at this point, we recommend that you allow notes access, otherwise some features might not work, and when that happens you might not remember that it is the API key that is blocking notes access. You can always edit the API key later.
We recommend that you use Per group permissions so that access is strictly restricted to the chosen group. Make sure that Read Only is selected for that group. This will grant read-only access to all items of that group, including notes.
This parameter is required and has no default value.
Type: String
"},{"location":"config-params/#zotero_library_id","title":"ZOTERO_LIBRARY_ID
","text":"The identifier of the Zotero library to get data from.
Finding your library ID:
Personal libraryGroup libraryFor a personal library, the value is your userID, as found on zotero.org (you must be logged-in).
For a group library this value is the groupID of the library, as found in the URL of the library (e.g., the groupID of the library at https://www.zotero.org/groups/2348869/kerko_demo
is \"2348869\"
).
This parameter is required and has no default value.
Type: String
"},{"location":"config-params/#zotero_library_type","title":"ZOTERO_LIBRARY_TYPE
","text":"The type of library to get data from, either \"user\"
for a personal library, or \"group\"
for a group library.
This parameter is required and has no default value.
Type: String
"},{"location":"config-params/#kerkobib_formats","title":"kerko.bib_formats.*.
","text":"Bibliographic record download formats, where *
is a format key.
The default formats are:
bibtex
ris
The configuration system does not allow adding new formats.
"},{"location":"config-params/#enabled","title":"enabled
","text":"Enable the format. If this is set to false
, the format will not be available through any download link.
Type: Boolean
Modifies the cache and the search index
Changing this parameter from false
to true
will require that you run the sync cache --full
and sync index
commands. See synchronization commands for details.
extension
","text":"File extension of the downloadable file.
Type: String
"},{"location":"config-params/#help_text","title":"help_text
","text":"Description of the format, to show in the help window.
Type: String
"},{"location":"config-params/#label","title":"label
","text":"Label to use in the format selector.
Type: String
"},{"location":"config-params/#mime_type","title":"mime_type
","text":"MIME type of the downloadable format.
Type: String
"},{"location":"config-params/#weight","title":"weight
","text":"Relative position of the format in lists. Formats with low weights (small numbers) rise above heavier ones (large numbers).
Type: Integer
"},{"location":"config-params/#kerkobreadcrumb","title":"kerko.breadcrumb.
","text":"A breadcrumb is a navigational aid that displays the location of the current page in relation to the structure of a website.
If enabled, the breadcrumb works in relation with the kerko.link_groups.breadcrumb_base
parameter, which defines the base (starting links) of the breadcrumb trail, which Kerko dynamically completes with one or more links based on the current location within Kerko.
enabled
","text":"Enable the breadcrumb.
Type: Boolean Default value: true
include_current
","text":"Include the current page at the end of the breadcrumb trail. If set to false
, the breadcrumb trail will end with the parent page instead of the current page.
Type: Boolean Default value: true
text_max_length
","text":"Maximum length for a breadcrumb item's text (in number of characters). If text is to be truncated in the middle of a word, the whole word is discarded instead. Truncated text is appended with an ellipsis sign (\"...\").
If set to 0
, no truncation will be applied.
Type: Integer Default value: 50
text_max_length_leeway
","text":"If the length of a breadcrumb item's text only exceeds kerko.breadcrumb.text_max_length
by this tolerance margin or less (in number of characters), the text will not be truncated.
This parameter has no effect if text_max_length
is set to 0
(no truncation).
Type: Integer Default value: 10
kerko.facets.*.
","text":"Facets to provide in the search interface, where *
is a facet key. The facet key is used internally by Kerko to identify the facet.
The default facets are:
item_type
(item types facet, enabled by default)language
(item languages facet, disabled by default)link
(items with links facet, disabled by default)tag
(item tags facet, enabled by default)year
(item years facet, enabled by default)You may define additional facets. See Defining custom facets based on Zotero collections.
Modifies the search index
Most of the kerko.facets.*
parameters require that you run the clean index
and sync index
commands after you have changed them. See synchronization commands for details.
collection_key
","text":"Key of the Zotero collection to map the facet to. This must refer to a top-level collection containing at least one hierarchical level of subcollections. Each subcollection will be mapped to a filter under the facet, if it contains at least one item that is not excluded through the kerko.zotero.item_include_re
or kerko.zotero.item_exclude_re
parameters.
This parameter has no default value and is required for facets whose type
parameter is set to \"collection\"
.
Type: String
"},{"location":"config-params/#enabled_2","title":"enabled
","text":"Enable the facet.
Type: Boolean Default value: depends on which facet you are looking at.
"},{"location":"config-params/#filter_key","title":"filter_key
","text":"Key to use in URLs when filtering with the facet.
Type: String Default value: depends on which facet you are looking at.
"},{"location":"config-params/#initial_limit","title":"initial_limit
","text":"Maximum number of filters to show by default under the facet. Excess filters will be shown if the user clicks a \"view more\" button. A value of 0
means no limit.
Type: Integer Default value: depends on which facet you are looking at.
"},{"location":"config-params/#initial_limit_leeway","title":"initial_limit_leeway
","text":"If the number of filters under the facet exceeds initial_limit
by this tolerance margin or less, all filters will be shown. A value of 0
means no tolerance margin.
Type: Integer Default value: depends on which facet you are looking at.
"},{"location":"config-params/#item_view","title":"item_view
","text":"Show the facet on item view pages.
Type: Boolean Default value: depends on which facet you are looking at.
"},{"location":"config-params/#sort_by","title":"sort_by
","text":"List of criteria used for sorting the filters under the facet. Allowed values in this list are \"count\"
and \"label\"
.
Type: Array of strings Default value: depends on which facet you are looking at.
"},{"location":"config-params/#sort_reverse","title":"sort_reverse
","text":"Reverse the sort order of the filters under the facet.
Type: Boolean Default value: depends on which facet you are looking at.
"},{"location":"config-params/#title","title":"title
","text":"Heading of the facet.
Type: String Default value: depends on which facet you are looking at.
"},{"location":"config-params/#type","title":"type
","text":"Type of facet. Determines the data source of the facet.
Allowed values are:
\"collection\"
: Use a Zotero collection as source.\"item_type\"
: Use the item type as source.\"language\"
: Use item Language field as source.\"link\"
: Use item URL field as source.\"tag\"
: Use Zotero tags as source.\"year\"
: Use the item year field as source.This parameter is required and has no default value.
Type: String
"},{"location":"config-params/#weight_1","title":"weight
","text":"Relative position of the facet in lists. Facets with low weights (small numbers) rise above heavier ones (large numbers).
Type: Integer Default value: depends on which facet you are looking at.
"},{"location":"config-params/#kerkofacetslanguage","title":"kerko.facets.language.
","text":"The parameters in this section only apply to the language
facet.
Source values for the language facet are extracted from the Language field of Zotero items.
"},{"location":"config-params/#allow_invalid","title":"allow_invalid
","text":"Allow values that are not found in the pycountry language database.
This parameter has an effect only if normalize
is set to true
.
If this parameter is set to true
, non-standard or badly entered language names will be allowed to appear in the language facet. You may find that you have to clean your data in Zotero if you wish to make the facet usable.
If this parameter is set to false
, non-standard or badly entered language names will be omitted from the language facet. The facet will only show recognized languages but may give an incomplete picture of all the languages present in your library.
Type: Boolean Default value: true
locale
","text":"The locale to use when displaying language names in the language facet. Translations are provided by pycountry.
This parameter has an effect only if normalize
is set to true
.
Type: String Default value: \"en\"
normalize
","text":"Normalize language names using the pycountry language database.
If this parameter is set to true
, slight inconsistencies in your data can be attenuated, preventing unwanted duplicates in the facet. For example, values such as fr
, FR
, fra
, Fra
, fre
, fr-FR
, fr-fr
, fr-CA
, or French
will all fall under a single French
term in the facet. The normalization process is case insensitive, ignores country or area codes, and recognizes:
Terms not falling into any of the above categories will be considered invalid. To choose what to do with invalid terms, see the allow_invalid
parameter.
For the best results with the normalize
option, we recommend that you record languages in Zotero using 2-letter ISO 639-1 codes (because they also happen to be supported by the Citation Style Language), or 3-letter ISO 639-3 codes for languages not covered by ISO 639-1.
If normalize
is set to false
, item language values will be used verbatim. In that case, the facet will work equally well if your language data is well controlled and consistent. This is the way to go if languages are consistently recorded using their non-English names in your Zotero library.
Type: Boolean Default value: true
values_separator_re
","text":"Regular expression to use for splitting the content of Zotero's Language field into multiple languages, e.g., en; de; it
. We do not necessarily recommend recording multiple languages in the Language field, but in practice some people do when describing multilingual resources.
Type: String Default value: \";\"
kerko.features.
","text":""},{"location":"config-params/#download_attachment_new_window","title":"download_attachment_new_window
","text":"Open attachments in new tabs. In other words: add the HTML target=\"_blank\"
attribute to attachment links.
Type: Boolean Default value: false
download_item
","text":"Provide a record download button on item pages.
To configure the bibliographic formats made available for downloading, see kerko.bib_formats
.
Type: Boolean Default value: true
download_results
","text":"Provide a record download button on search results pages.
To configure the bibliographic formats made available for downloading, see kerko.bib_formats
.
Type: Boolean Default value: true
download_results_max_count
","text":"Limit over which the record download button should be hidden from search results pages.
Type: Integer Default value: 0
(i.e., no limit)
open_in_zotero_app
","text":"On item pages, show a button for opening the corresponding item in the Zotero application (through a link using the zotero://
protocol). If this parameter is set to true
, a user will still need to first enable the button from the Preferences menu (which can be accessed from the footer of item pages and saves the user's choices in browser cookies). For the link to work, the user must also have the Zotero application installed, and have access to the Zotero library. This feature is generally only useful to library editors and might confuse other users, especially if your Zotero library is private. Thus you should probably enable this option only if there is a strong need from the editors.
Type: Boolean Default value: false
open_in_zotero_web
","text":"On item pages, show a button for viewing the corresponding item on zotero.org (through a regular hyperlink). If this parameter is set to true
, a user will still need to first enable the button from the Preferences menu (which can be accessed from the footer of item pages and saves the user's choices in browser cookies). For the link to work, the user must also have access to the Zotero library. This feature is generally only useful to library editors and might confuse other users, especially if your Zotero library is private. Thus you should probably enable this option only if there is a strong need from the editors.
Type: Boolean Default value: false
print_item
","text":"Provide a print button on item pages.
Type: Boolean Default value: false
print_results
","text":"Provide a print button on search results pages.
Type: Boolean Default value: false
print_results_max_count
","text":"Limit over which the print button should be hidden from search results pages.
Type: Integer Default value: 0
(i.e., no limit)
relations_initial_limit
","text":"Number of related items to show above the \"show more\" link.
Type: Integer Default value: 5
relations_links
","text":"Show item links in lists of related items.
Enabling this only has an effect if at least one of the following variables is also set to true
: kerko.features.results_attachment_links
, kerko.features.results_url_links
.
Type: Boolean Default value: false
results_abstracts
","text":"Show abstracts on search result pages.
Type: Boolean Default value: false
(i.e., hide abstracts)
results_abstracts_toggler
","text":"Show a button letting users show or hide abstracts on search results pages.
Type: Boolean Defaults value: true
(i.e., toggle is displayed)
results_abstracts_max_length
","text":"Truncate abstracts at the given length (in number of characters). If text is to be truncated in the middle of a word, the whole word is discarded instead. Truncated text is appended with an ellipsis sign (\"...\").
Type: Integer Default value: 0
(i.e., abstracts get displayed in their full length, without any truncation)
results_abstracts_max_length_leeway
","text":"If the length of an abstract only exceeds kerko.features.results_abstracts_max_length
by this tolerance margin or less (in number of characters), it will not be truncated.
This parameter has no effect if results_abstracts_max_length
is set to 0
(no truncation).
Type: Integer Default value: 0
(i.e., no tolerance margin).
results_attachment_links
","text":"Provide links to attachments in search results.
Type: Boolean Default value: true
results_url_links
","text":"Provide links to online resources in search results (for items whose URL field has a value).
Type: Boolean Default value: true
kerko.feeds.
","text":""},{"location":"config-params/#formats","title":"formats
","text":"A list of syndication feed formats to publish.
If set to an empty array, no web feed will be provided. The only supported format at this time is 'atom'
.
Type: Array of strings Default value: [\"atom\"]
fields
","text":"List of fields to retrieve for each feed item. Values in this list are keys identifying fields defined in the kerko_composer
object, and the list must contain all fields that are used by the kerko.templates.atom_feed
template.
One probably only needs to change the default list when overriding the template to display additional fields.
Note that some fields from the default list may be required by Kerko, and removing those could cause crashes.
Type: Dictionary
"},{"location":"config-params/#max_days","title":"max_days
","text":"The age (in number of days) of the oldest items allowed into web feeds. The date field of the items is used for that purpose, and when no date is available, the date the item was added to Zotero is used instead.
Unless your goal is to promote recent literature only, you should probably keep the default value.
Items with missing dates will be considered as very recent, to prevent them from being excluded from feeds. For the same reason, items whose date lack the month and/or the day will be considered as from the 12th month of the year and/or the last day of the month.
Type: Integer Default value: 0
(i.e., no age limit)
kerko.link_groups.*.
","text":"Link groups, where *
is an arbitrary key used for identifying the group. Each group is a list which must contain at least one link defined using one or more of the sub-parameters described below.
Link groups can be used for navigation or anywhere hyperlinks are needed. Templates can use the key to retrieve a desired link group.
Kerko provides default navbar
and breadcrumb_base
link groups. In TOML format, these are defined as below (the double brackets indicate a list item):
[[kerko.link_groups.navbar]]\ntype = \"endpoint\"\nendpoint = \"kerko.search\"\ntext = \"Bibliography\"\n\n[[kerko.link_groups.breadcrumb_base]]\ntype = \"endpoint\"\nendpoint = \"kerko.search\"\ntext = \"Bibliography\"\n
"},{"location":"config-params/#anchor","title":"anchor
","text":"Anchor to append to the endpoint's URL.
This optional parameter is only allowed when the type
parameter is set to \"endpoint\"
.
Type: String
"},{"location":"config-params/#endpoint","title":"endpoint
","text":"Name of the endpoint within the application to use as target for the link. Use this for internal links. For example, the endpoint for the Kerko search page is \"kerko.search\"
.
This parameter is required if the type
parameter is set to \"endpoint\"
and has no default value.
Type: String
"},{"location":"config-params/#external","title":"external
","text":"Generate a full URL (with scheme and domain) for the endpoint instead of an internal URL.
This parameter is only allowed when the type
parameter is set to \"endpoint\"
.
Type: Boolean Default value: false
new_window
","text":"Open the link in a new tab.
Type: Boolean Default value: false
page
","text":"Key of the page to use as target for the link. That page must have been defined in kerko.pages.*
.
This parameter is required if the type
parameter is set to \"page\"
(and cannot be used with other type
values).
Type: String
"},{"location":"config-params/#parameters","title":"parameters
","text":"Dictionary of parameters to pass to the endpoint. Unknown keys are appended to the URL as query string arguments, like ?a=b&c=d
.
This optional parameter is only allowed when the type
parameter is set to \"endpoint\"
.
Type: Dictionary
"},{"location":"config-params/#scheme","title":"scheme
","text":"Protocol to use in the endpoint's URL.
This parameter is only allowed when the type
parameter is set to \"endpoint\"
and the external
parameter is set to true
.
Type: String Default value: Same protocol as the current request
"},{"location":"config-params/#text","title":"text
","text":"Text to use for the link.
This parameter is required and has no default value.
Type: String
"},{"location":"config-params/#type_1","title":"type
","text":"Type of link being configured. Other parameters may or may not be available depending on this value.
Allowed values are:
\"endpoint\"
: Link to an application page (served by a Flask endpoint).\"page\"
: Link to a page defined in kerko.pages.*
.\"url\"
: Link to an arbitrary URL.This parameter is required and has no default value.
Type: String
"},{"location":"config-params/#url","title":"url
","text":"URL of the external link.
This parameter is required if the type
parameter is set to \"url\"
.
Type: String
"},{"location":"config-params/#weight_2","title":"weight
","text":"Relative position of the link in lists. Links with low weights (small numbers) rise above heavier ones (large numbers). At equal weights, links are ordered based on their order of appearance in the configuration.
Type: Integer Default value: 0
kerko.meta.
","text":""},{"location":"config-params/#google_analytics_id","title":"google_analytics_id
","text":"A Google Analytics measurement ID, e.g., 'G-??????????'
.
If the value is not empty and Flask is not running in debug mode, then the Google Analytics tag is inserted into the pages.
Type: String Default value: \"\"
highwirepress_tags
","text":"Embed Highwire Press tags into the HTML of item pages. This should help search engines such as Google Scholar index your items more accurately, but works only with book, conference paper, journal article, report or thesis items.
Type: Boolean Default value: true
(i.e., enabled).
title
","text":"The title to display in web pages.
Type: String
"},{"location":"config-params/#kerkopages","title":"kerko.pages.*.
","text":"Simple content pages, where *
is an arbitrary key you must choose to uniquely identify the page. The content of the page will come from a Zotero standalone note of your choosing.
The key can be used in kerko.link_groups.*
tables to define hyperlinks to the page.
path
","text":"The path to use in the URL of the page. Must start with a slash (/
) character.
Type: String
"},{"location":"config-params/#item_id","title":"item_id
","text":"The Zotero item ID of the note to use as content for the page.
Type: String
"},{"location":"config-params/#title_2","title":"title
","text":"The title of the page.
Type: String
"},{"location":"config-params/#kerkopagination","title":"kerko.pagination.
","text":""},{"location":"config-params/#page_len","title":"page_len
","text":"The number of search results per page.
Type: Integer Default value: 20
pager_links
","text":"Number of pages to show in the pager (not counting the current page).
Type: Integer Default value: 4
kerko.performance.
","text":""},{"location":"config-params/#whoosh_index_memory_limit","title":"whoosh_index_memory_limit
","text":"Maximum memory (in megabytes) the Whoosh index writer will use for the indexing pool. The higher the number, the faster indexing will be.
The actual memory used will be higher than this value because of interpreter overhead (up to twice as much!). Other operations performed by Kerko at indexing time use memory too. Thus, although useful as a tuning parameter, this setting does not allow to exactly control the memory usage.
Type: Integer Default value: 128
"},{"location":"config-params/#whoosh_index_processors","title":"whoosh_index_processors
","text":"Controls the number of processors Whoosh will use for indexing.
Note that when you use multiprocessing, the whoosh_index_memory_limit
parameter controls the amount of memory used by each process, so the actual memory used will be whoosh_index_memory_limit
\u00d7 whoosh_index_processors
.
Type: Integer Default value: 1
"},{"location":"config-params/#kerkoscopes","title":"kerko.scopes.*.
","text":"Keyword search scopes, where *
is a scope key. The scope key is used internally by Kerko to identify the scope. Scopes allow users to restrict the search to some fields.
The default scopes are:
all
creator
fulltext
metadata
pubyear
title
You may define additional scopes.
To link fields to scopes, see kerko.search_fields.scopes
.
breadbox_label
","text":"Label to use when the scope appears in the breadbox, i.e. in the list of search criteria.
"},{"location":"config-params/#enabled_3","title":"enabled
","text":"Enable the scope.
Type: Boolean
"},{"location":"config-params/#help_text_1","title":"help_text
","text":"Description of the scope, to show in the help window.
Type: String
"},{"location":"config-params/#selector_label","title":"selector_label
","text":"Label to use in the scope selector.
Type: String
"},{"location":"config-params/#weight_3","title":"weight
","text":"Relative position of the scope in lists. Scopes with low weights (small numbers) rise above heavier ones (large numbers).
Type: Integer
"},{"location":"config-params/#kerkosearch","title":"kerko.search.
","text":""},{"location":"config-params/#fulltext","title":"fulltext
","text":"Allow full-text search of PDF attachments.
Type: Boolean Default value: true
Tip
To get consistent results with full-text search, see Ensuring full-text indexing of your attachments in Zotero.
Tip
When setting kerko.search.fulltext
to false
, it is recommended that you set kerko.scopes.fulltext.enabled
and kerko.scopes.metadata.enabled
to false
as well. With full-text data unavailable, the fulltext
scope is useless, and the metadata
scope gives the same results as the all
scope.
Modifies the cache and the search index
Changing this parameter will require that you run the sync cache --full
and sync index
commands. See synchronization commands for details.
result_fields
","text":"List of item fields to retrieve for search results (most notably used by the kerko.templates.search_item
template).
Values in this list are keys identifying fields defined in the kerko.composer.Composer
instance. One probably only needs to change the default list when overriding the template to display additional fields.
Note that some fields from the default list may be required by Kerko, and removing those could cause crashes.
Type: Array of strings Default value: [\"id\", \"attachments\", \"bib\", \"coins\", \"data\", \"url\"]
whoosh_language
","text":"The language of search requests.
As of this writing, Whoosh supports the following languages: ar, da, nl, en, fi, fr, de, hu, it, no, pt, ro, ru, es, sv, tr. You may refer to Whoosh's source code to get the list of supported languages (see whoosh.lang.languages
) and the list of languages that support stemming (see whoosh.lang.has_stemmer()
).
Type: String Default value: \"en\"
Modifies the search index
Changing this parameter will require that you run the sync index --full
command. See synchronization commands for details.
kerko.search_fields.*.
","text":"Searchable fields, where *
is a field key. The default fields fall into different tables:
core.optional.*
: These fields have limited parameters. Their only allowed parameters are boost
, enabled
, and scopes
.core.required.*
: These fields cannot be disabled. Their only allowed parameters are boost
and scopes
.zotero.*
: These fields derive directly from Zotero item fields and allow all field parameters.The configuration system does not allow adding new fields.
Modifies the search index
Changing any of the kerko.search_fields.*
parameters will require that you run the clean index
and sync index
commands, except if you are just disabling a field or changing its scopes
parameter. See synchronization commands for details.
analyzer
","text":"Type of analysis to apply to the field value when building the search index.
Allowed values:
\"id\"
: Index the entire value of the field as one token.\"name\"
: Apply standard tokenization and filtering, but without stemming.\"text\"
: Apply standard tokenization, stemming and filtering.Type: String
"},{"location":"config-params/#boost","title":"boost
","text":"Scaling factor to apply to score when matches are found in the field.
Type: Float
"},{"location":"config-params/#enabled_4","title":"enabled
","text":"Enable the field.
Type: Boolean
"},{"location":"config-params/#scopes","title":"scopes
","text":"List of keyword search scopes that will exploit the field.
Allowed values are determined by kerko.scopes
.
Type: Array of strings
"},{"location":"config-params/#kerkosorts","title":"kerko.sorts.*.
","text":"Search results sorting options, where *
is a sort option key.
The default sort options are:
author_asc
author_desc
date_asc
date_desc
score
title_asc
title_desc
The configuration system does not allow adding new sort options.
"},{"location":"config-params/#enabled_5","title":"enabled
","text":"Enable the sort option.
Type: Boolean
"},{"location":"config-params/#label_1","title":"label
","text":"Label of the sort option.
Type: String
"},{"location":"config-params/#weight_4","title":"weight
","text":"Relative position of the sort option in lists. Sort options with low weights (small numbers) rise above heavier ones (large numbers).
The default sort option will be the one with the lowest weight.
Type: Integer
Tip
It is recommended that kerko.sorts.score.weight
has the smallest value of all your sort options. Thus, when a keyword search is performed, sorting by relevance score will be the default, and when no keywords are used in the search, then the sort option with the second smallest weight will be the default one.
kerko.templates.
","text":""},{"location":"config-params/#search","title":"search
","text":"Name of the Jinja2 template to render for the search page with list of results.
Type: String Default value: \"kerko/search.html.jinja2\"
search_item
","text":"Name of the Jinja2 template to render for the search page with a single bibliographic record.
Type: String Default value: \"kerko/search-item.html.jinja2\"
item
","text":"Name of the Jinja2 template to render for the bibliographic record view.
Type: String Default value: \"kerko/item.html.jinja2\"
atom_feed
","text":"Name of the Jinja2 template used to render an Atom feed.
Type: String Default value: \"kerko/atom.xml.jinja2\"
layout
","text":"Name of the Jinja2 template that is extended by the search, search-item, and item templates.
Type: String Default value: \"kerko/layout.html.jinja2\"
base
","text":"Name of the Jinja2 template that is extended by the layout template.
Type: String Default value: \"kerko/base.html.jinja2\"
kerko.zotero.
","text":""},{"location":"config-params/#attachment_mime_types","title":"attachment_mime_types
","text":"List of allowed MIME types for attachments.
Type: Array of strings Default value: [\"application/pdf\"]
Modifies the attachments
Changing this parameter will require that you run the sync attachments
command. See synchronization commands for details.
csl_style
","text":"The citation style to use for formatted references.
Allowed values are either a file name (without the .csl
extension) found in the Zotero Styles Repository (e.g., \"apa\"
) or the publicly accessible URL of a remote CSL file.
Type: String Default value: \"apa\"
.
Modifies the cache and the search index
Changing this parameter will require that you run the sync cache --full
and sync index
commands. See synchronization commands for details.
batch_size
","text":"Number of items to request on each call to the Zotero API.
Type: Integer Default value: 100
(this is the maximum currently allowed by the Zotero API)
child_include_re
","text":"Regular expression to use to include children (e.g. notes, attachments) based on their tags. Any child which does not have a tag that matches this regular expression will be ignored. If this value is empty (which is the default), all children will be accepted unless kerko.zotero.child_exclude_re
is set and causes some to be rejected.
Type: String Default value: \"\"
Modifies the search index and attachments
Changing this parameter will require that you run the sync index --full
and sync attachments
commands. See synchronization commands for details.
child_exclude_re
","text":"Regular expression to use to exclude children (e.g. notes, attachments) based on their tags. Any child that have a tag that matches this regular expression will be ignored. If empty, no children will be rejected unless kerko.zotero.child_include_re
is set and the tags of those children do not match it. By default, any child having at least one tag that begins with an underscore character (_
) is rejected.
Type: String Default value: \"^_\"
Modifies the search index and attachments
Changing this parameter will require that you run the sync index --full
and sync attachments
commands. See synchronization commands for details.
item_include_re
","text":"Regular expression to use to include items based on their tags. Any item which does not have a tag that matches this regular expression will be ignored. If this value is empty (which is the default), all items will be accepted unless kerko.zotero.item_exclude_re
is set which can cause some items to be rejected.
Type: String Default value: \"\"
Modifies the search index and attachments
Changing this parameter will require that you run the sync index --full
and sync attachments
commands. See synchronization commands for details.
item_exclude_re
","text":"Regular expression to use to exclude items based on their tags. Any item that have a tag that matches this regular expression will be excluded. If empty (which is the default), no items will be excluded unless kerko.zotero.item_include_re
is set, in which case items that do not have any tag that matches it will be excluded.
Type: String Default value: \"\"
Modifies the search index and attachments
Changing this parameter will require that you run the sync index --full
and sync attachments
commands. See synchronization commands for details.
locale
","text":"The locale to use with Zotero API calls. This dictates the locale of Zotero item types, field names, creator types and citations. Supported locales are listed at https://api.zotero.org/schema, under \"locales\".
Type: String Default value: \"en-US\"
Modifies the cache and the search index
Changing this parameter will require that you run the sync cache --full
and sync index
commands. See synchronization commands for details.
max_attempts
","text":"Maximum number of tries after the Zotero API has returned an error or has not responded during indexing.
Type: Integer Default value: 10
tag_include_re
","text":"Regular expression to use to include tags. By default, all tags are accepted.
Note that record exports (downloads) always include all tags regardless of this parameter, which only applies to information displayed by Kerko (exports are generated by the Zotero API, not by Kerko).
Type: String Default value: \"\"
Modifies the search index
Changing this parameter will require that you run the sync index --full
command. See synchronization commands for details.
tag_exclude_re
","text":"Regular expression to use to exclude tags. The default value causes any tag that begins with an underscore character (_
) to be ignored by Kerko.
Note that record exports (downloads) always include all tags regardless of this parameter, which only applies to information displayed by Kerko (exports are generated by the Zotero API, not by Kerko).
Type: String Default value: \"^_\"
Modifies the search index
Changing this parameter will require that you run the sync index --full
command. See synchronization commands for details.
wait
","text":"Time to wait (in seconds) between failed attempts to call the Zotero API.
Type: Integer Default value: 120
kerkoapp.proxy_fix.
","text":"When an application is running behind a proxy server, WSGI may see the request as coming from that server rather than the real client. Proxies set various headers to track where the request actually came from.
In that case you must tell the application how many proxies set each header so it knows what values to trust. However, enable this ONLY if the application is actually running behind a proxy; it would be a security issue to trust values that came directly from the client rather than a proxy.
Refer to Tell Flask it is behind a proxy for details.
Warning
This parameter is specific to KerkoApp.
"},{"location":"config-params/#enabled_6","title":"enabled
","text":"Enable the proxy parameters.
All other kerkoapp.proxy_fix
parameters are ignored unless this is set to true
.
Type: Boolean Default value: false
x_for
","text":"Number of values to trust for X-Forwarded-For
.
Type: Integer Default value: 1
x_proto
","text":"Number of values to trust for X-Forwarded-Proto
.
Type: Integer Default value: 1
x_host
","text":"Number of values to trust for X-Forwarded-Host
.
Type: Integer Default value: 0
x_port
","text":"Number of values to trust for X-Forwarded-Port
.
Type: Integer Default value: 0
x_prefix
","text":"Number of values to trust for X-Forwarded-Prefix
.
Type: Integer Default value: 0
This section provides guidance on how to contribute to the Kerko project.
"},{"location":"contributing/#reporting-issues","title":"Reporting issues","text":"Before reporting an issue, please consider the following guidelines:
Clone the Kerko repository into a local directory. Set up a virtual environment, then install that local version of Kerko in the virtual environment, including development and testing dependencies by running the following command from Kerko's root directory, i.e., where setup.cfg
resides:
pip install -e .[dev,docs,tests]\n
"},{"location":"contributing/#running-the-tests","title":"Running the tests","text":"To run the test suite:
python -m unittest\n
To check code coverage as well, use these commands instead:
coverage run -m unittest\ncoverage report\n
To run the full test suite under different environments (using the various Python interpreters available on your machine):
tox\n
Note
Test coverage is still low at the moment. You are welcome to contribute new tests!
"},{"location":"contributing/#running-the-pre-commit-hooks","title":"Running the pre-commit hooks","text":"Pre-commit checks should be performed automatically whenever you perform a git commit
. If you wish to run the checks manually, use this command:
pre-commit run --all-files\n
"},{"location":"contributing/#working-on-the-documentation","title":"Working on the documentation","text":"To start a local live-reloading documentation server:
mkdocs serve\n
Then view the documentation in your browser at http://localhost:8000/.
"},{"location":"contributing/#building-the-distribution-package","title":"Building the distribution package","text":"When building the distribution package, a version number is dynamically extracted from the Git repository. For an official release, the Git head revision must be tagged prior to building the distribution package. When the revision is not tagged, a dev version number gets derived from the branch's most recent tag, with a suffix appended.
To check the version number that will be generated:
hatch version\n
To build the distribution package in sdist and wheel formats:
hatch build\n
"},{"location":"contributing/#submitting-code-changes","title":"Submitting code changes","text":"Pull requests may be submitted against Kerko's repository. Please consider the following guidelines:
Some guidelines:
Please submit your translation as a pull request against the proper repository, either Kerko's, or KerkoApp's, or by e-mail, with the PO file included as an attachment (do not copy the PO file's content into an e-mail's body, since that could introduce formatting or encoding issues).
"},{"location":"contributing/#supporting-the-project","title":"Supporting the project","text":"Nurturing an open source project, following up on issues and helping others in working with the system is a lot of work. Hiring the original developers of Kerko can help make the project sustainable. It is the best way to ensure continued support and development of the project.
If you need professional support related to Kerko, have requirements not currently implemented in Kerko, want to make sure that some Kerko issue important to you gets resolved, or if you just like our work and would like to hire us for an unrelated project, please e-mail us.
"},{"location":"deploying/","title":"How to deploy","text":"As there is a great diversity of operating systems, hosting environments, and WSGI servers, it is hard to provide universal and useful instructions for setting up KerkoApp for use in production.
You can expect a procedure similar to that of any Flask application, and there are many guides on the web covering this topic for various environments.
That said, you may refer to the guide below for step-by-step instructions. Even if your environment is different from the one this guide was designed for, it might provide you with some useful hints.
"},{"location":"deploying/#deploying-on-ubuntu-with-nginx-and-gunicorn","title":"Deploying on Ubuntu with nginx and gunicorn","text":"These instructions will detail the steps and configurations required to get KerkoApp running on an Ubuntu 22.04 or 24.04 web server, using Gunicorn as the WSGI container and nginx as a HTTP proxy.
The procedure is similar that of any Flask application, but KerkoApp-specific steps are also covered here.
Install some required packages, including Python 3:
sudo apt install git nginx python3 python3-pip python3-venv\n
Create the user who will run the app:
sudo groupadd --system kerkoapp\nsudo useradd --gid kerkoapp --shell /bin/bash --create-home --home-dir /home/kerkoapp --groups www-data kerkoapp\n
Switch to that user and clone the desired version of KerkoApp. If you want to use version 1.0.0, for example, replace VERSION
in the command below with 1.0.0
:
sudo su kerkoapp\ngit clone --branch VERSION https://github.com/whiskyechobravo/kerkoapp.git ~/kerkoapp\n
Still as user kerkoapp
, create a Python virtual environment and install the Python packages required by KerkoApp:
python3 -m venv ~/venv\nsource ~/venv/bin/activate\npip3 install -r ~/kerkoapp/requirements/run.txt\npip3 install gunicorn\n
Always as user kerkoapp
, create the ~/.secrets.toml
file. This is where you will put secret keys that should only be known to your server. Its content should look like the following:
SECRET_KEY = \"MY_SECRET_KEY\"\nZOTERO_API_KEY = \"MY_ZOTERO_API_KEY\"\n
You must set SECRET_KEY
with a random string, and ZOTERO_API_KEY
with an appropriate value (see configuration parameters).
Then create the ~/instance.toml
file. This file will contain settings that are specific to your server, but are not secret. Its content should look like the following:
LOGGING_HANDLER = \"syslog\"\n\n[kerkoapp.proxy_fix]\nenabled = true\nx_for = 1\nx_proto = 1\nx_host = 1\nx_port = 0\nx_prefix = 0\n
We are enabling the kerkoapp.proxy_fix
parameters because we will configure nginx as a reverse proxy.
Then create the ~/config.toml
file. This file will contain general settings for Kerko. You might have already tested KerkoApp on your desktop computer and created such file. If so, you could just copy that file to your server. At the very least it should contain the following settings:
ZOTERO_LIBRARY_ID = \"MY_ZOTERO_LIBRARY_ID\"\nZOTERO_LIBRARY_TYPE = \"MY_ZOTERO_LIBRARY_TYPE\"\n\n[kerko.meta]\ntitle = \"My Bibliography\"\n
You must set ZOTERO_LIBRARY_ID
and ZOTERO_LIBRARY_TYPE
with appropriate values (see configuration parameters) so that Kerko can connect to your Zotero library.
It is not absolutely necessary to use three separate configuration files for KerkoApp as we just did. You could, for example, have just ~/instance.toml
and put all of the settings there. However, it is a good practice to split the configuration, and that allows you to copy config.toml
from or to other machines, or even share it with other people, without worrying about leaking secret keys or messing up your server-specific settings.
Once the configuration files are ready, Kerko should be able to talk to Zotero. Have Kerko retrieve your Zotero library's data by running the following command:
flask --debug kerko sync\n
The --debug
switch is optional. If you use it, some messages will give you an better idea of the progress of the sync process. If you omit it, the command will run silently unless there are warnings or errors.
Depending on the size of your library, this process can complete within less than a minute or take an hour or more. Zotero throttles API requests to prevent its servers from getting overloaded, so sometimes the process might seem to freeze, but be patient and Kerko will resume synchronization a few minutes later.
Now that synchronization works, configure the cron task that will synchronize data from your Zotero library on a regular basis. Run the following command (always from the kerkoapp
user):
crontab -e\n
That will launch the default nano
editor. Add the following line at the very bottom, then save the file and exit the editor:
10 4 * * * cd /home/kerkoapp/kerkoapp && /home/kerkoapp/venv/bin/flask kerko sync\n
That will synchronize the data once a day, at 4:10am. You may specify a different time, of course.
Now exit from the kerkoapp
user's shell, and go back to your usual sudoer account to finish the installation.
Configure a socket that will let Gunicorn to speak with nginx. As the superuser, create the /etc/systemd/system/kerkoapp.socket
file, with the following content:
[Unit]\nDescription=KerkoApp socket\n\n[Socket]\nListenStream=/run/kerkoapp.socket\n\n[Install]\nWantedBy=kerkoapp.target\n
Configure a service that will run Gunicorn. As the superuser, create the /etc/systemd/system/kerkoapp.service
file, with the following content:
[Unit]\nDescription=KerkoApp daemon\nRequires=kerkoapp.socket\nAfter=network.target\n\n[Service]\nWorkingDirectory=/home/kerkoapp/kerkoapp\nExecStart=/home/kerkoapp/venv/bin/gunicorn wsgi:app --name kerkoapp --user kerkoapp --group www-data --workers 4 --log-level warning --error-logfile - --access-logfile - --bind unix:/run/kerkoapp.socket\nExecReload=/bin/kill -s HUP $MAINPID\nExecStop=/bin/kill -s TERM $MAINPID\nPrivateTmp=true\n\n[Install]\nWantedBy=multi-user.target\n
Reload the systemd configurations, then enable and start the new service by running the following commands:
sudo systemctl daemon-reload\nsudo systemctl enable kerkoapp.socket\nsudo systemctl enable kerkoapp.service\nsudo systemctl start kerkoapp.socket\n
You can check whether the socket is active with this command:
sudo systemctl status kerkoapp.socket\n
If it shows up as 'active (listening)', you may now verify that it triggers the service:
curl --unix-socket /run/kerkoapp.socket localhost\nsudo systemctl status kerkoapp.service\n
The curl
command should output some HTML, and the systemctl
command should now show the KerkoApp daemon as 'active (running)'.
If either the socket or the service doesn't work, you might want to check for errors in the log:
sudo journalctl --unit=kerkoapp\n
Once all of the above works, configure nginx to pass requests to Gunicorn. As the superuser, create the /etc/nginx/sites-available/kerkoapp.conf
file with the following content, replacing example.com
with your actual domain name:
server {\n listen 80;\n server_name example.com;\n\n location / {\n proxy_redirect off;\n proxy_set_header Host $http_host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Host $server_name;\n proxy_set_header X-Forwarded-Proto $scheme;\n\n if (!-f $request_filename) {\n proxy_pass http://unix:/run/kerkoapp.socket;\n break;\n }\n }\n}\n
Enable the site by running the following command:
sudo ln -s /etc/nginx/sites-available/kerkoapp.conf /etc/nginx/sites-enabled/\n
Have nginx test the configuration:
sudo nginx -t\n
If the command reports the configuration test as successful, reload nginx to make the configuration changes effective:
sudo service nginx reload\n
You should now be able to view your KerkoApp site at http://example.com!
The nginx configuration above will serve the application using the HTTP protocol. As for any website, HTTPS is strongly recommended. That will require that you install a SSL certificate and configure nginx to use it; that exercise is left to the reader.
Changing the configuration can be disruptive
Making any change to a configuration file requires that you at least restart the application afterwards for the change to become effective.
Moreover, some parameters have an effect on the structure of the cache or the search index that Kerko depends on. Changing this kind of parameter may require that you rebuild either. Refer to the documentation of the parameter to check if specific actions need to be taken after a change.
The commands below, for example, will allow you to clean and rebuild the search index, and to restart KerkoApp:
sudo -iu kerkoapp bash -c 'cd /home/kerkoapp/kerkoapp && /home/kerkoapp/venv/bin/flask kerko clean index'\nsudo -iu kerkoapp bash -c 'cd /home/kerkoapp/kerkoapp && /home/kerkoapp/venv/bin/flask kerko sync'\nsudo systemctl stop kerkoapp.socket\nsudo systemctl start kerkoapp.socket\n
"},{"location":"deploying/#submitting-your-sitemap-to-search-engines","title":"Submitting your sitemap to search engines","text":"Kerko generates an XML Sitemap that can help search engines discover your bibliographic records.
The path of the sitemap is BASE_URL/sitemap.xml
, where BASE_URL
should be replaced with the protocol, domain, port, and Kerko URL path prefix that are relevant to your installation, e.g., https://example.com/bibliography/sitemap.xml
.
Different search engines may have different procedures for submitting sitemaps (Google, Bing, Yandex).
However, a standard method consists in adding a Sitemap
directive to a robots.txt
file served at the root of your site, to tell web crawlers where to find your sitemap. For example, one might add the following line to robots.txt
:
Sitemap: https://example.com/bibliography/sitemap.xml\n
A robots.txt
file can have multiple Sitemap
directives, thus the Kerko sitemap can be specified alongside any other sitemaps you might already have.
For getting started with Kerko, we recommend that you use KerkoApp. However, if KerkoApp is not suited to your use case, we also have instructions for creating a custom application.
"},{"location":"getting-started/#getting-started-with-kerkoapp","title":"Getting started with KerkoApp","text":"To install KerkoApp, you may choose between a \"standard\" installation and a Docker installation. Just go with the option you feel most comfortable with. If you don't know Docker, you should be fine with the standard installation. But if you prefer to keep your distance from Python-related stuff, perhaps the Docker installation will suit you best.
"},{"location":"getting-started/#standard-installation","title":"Standard installation","text":"This procedure requires that you have Python, pip, and Git installed on your computer.
The first step is to install the desired version of KerkoApp. You may check the list of available versions, but make sure to choose one that matches the documentation version you are currently reading! For version 1.0.0, for example, replace VERSION
with 1.0.0
in the commands below:
git clone --branch VERSION https://github.com/whiskyechobravo/kerkoapp.git\ncd kerkoapp\npython -m venv venv\nsource venv/bin/activate\npip install -r requirements/run.txt\n
git clone --branch VERSION https://github.com/whiskyechobravo/kerkoapp.git\ncd kerkoapp\npython -m venv venv\nvenv\\Scripts\\activate.bat\npip install -r requirements\\run.txt\n
This will install all packages required by Kerko and KerkoApp within a virtual environment.
Copy the sample.secrets.toml
file to .secrets.toml
in the same directory. Open .secrets.toml
in a text editor to assign proper values to the parameters outlined below:
SECRET_KEY
: This parameter is required for generating secure tokens in web forms. It should have a hard to guess value, and should really remain secret. For this reason, never add your .secrets.toml
file to a code repository.ZOTERO_API_KEY
: Your Zotero API key. See API key creation instructions.Copy the sample.config.toml
file to config.toml
in the same directory. Open config.toml
in a text editor to assign proper values to the parameters outlined below:
ZOTERO_LIBRARY_ID
: The identifier of the Zotero library to get data from. For a personal library the value is your userID, as found on https://www.zotero.org/settings/keys (you must be logged-in). For a group library this value is the groupID of the library, as found in the URL of the library (e.g., the groupID of the library at https://www.zotero.org/groups/2348869/kerko_demo is \"2348869\"
).ZOTERO_LIBRARY_TYPE
: The type of library to get data from, either \"user\"
for a personal library, or \"group\"
for a group library.You do not need to edit other parameters at this point, but later on config.toml
is where your configuration changes will take place.
Have KerkoApp synchronize your data from zotero.org:
flask --debug kerko sync\n
If you have a large Zotero library and/or large file attachments, that command may take a while to complete. Wait until the command finishes. In production use, this command is usually added to the crontab file for regular execution.
The --debug
switch is optional. If you use it, some messages will give you an idea of the sync process' progress. If you omit it, the command will run silently unless there are warnings or errors.
To list all commands provided by Kerko:
flask kerko --help\n
Run KerkoApp:
flask --debug run\n
Open http://localhost:5000/ in your browser and explore the bibliography!
Running your installed application
To launch the application again in a future session, make sure to reactivate the virtual environment first. The command sequence should look like:
POSIXWindowscd kerkoapp\nsource venv/bin/activate\nflask --debug run\n
cd kerkoapp\nvenv\\Scripts\\activate.bat\nflask --debug run\n
Not suitable for production
The above procedure relies on Flask's built-in server, which is not suitable for production. For production use, you should consider better options such as the WSGI servers suggested in the Flask documentation.
"},{"location":"getting-started/#docker-installation","title":"Docker installation","text":"This procedure requires that Docker is installed on your computer.
Copy the Makefile
, sample.secrets.toml
, and sample.config.toml
files from the most recent stable branch of the KerkoApp repository (e.g. https://github.com/whiskyechobravo/kerkoapp/tree/stable/1.0.x) to an empty directory on your computer.
Under the same directory, create a subdirectory named instance
. This is where you will put your configuration files, and where Kerko will save its data.
Copy sample.secrets.toml
as .secrets.toml
into the instance
subdirectory. Open instance/.secrets.toml
in a text editor to assign proper values to the configuration parameters outlined below:
SECRET_KEY
: This parameter is required for generating secure tokens in web forms. It should have a hard to guess value, and should really remain secret. For this reason, never add your .secrets.toml
file to a code repository.ZOTERO_API_KEY
: Your Zotero API key. See API key creation instructions.Copy sample.config.toml
as config.toml
into the instance
subdirectory. Open instance/config.toml
in a text editor to assign proper values to the configuration parameters outlined below:
ZOTERO_LIBRARY_ID
: The identifier of the Zotero library to get data from. For a personal library the value is your userID, as found on https://www.zotero.org/settings/keys (you must be logged-in). For a group library this value is the groupID of the library, as found in the URL of the library (e.g., the groupID of the library at https://www.zotero.org/groups/2348869/kerko_demo is \"2348869\"
).ZOTERO_LIBRARY_TYPE
: The type of library to get data from, either \"user\"
for a personal library, or \"group\"
for a group library.It should not be necessary to change other settings at this point. You can always come back later to this file in order to configure KerkoApp to your liking. For now, we suggest that you proceed to the next step and get it running.
From the same directory as Makefile
, run KerkoApp:
make run\n
This command should do many things:
If your configuration files have errors, the process may be interrupted; if that happens, retry make run
after correcting the problem. Otherwise, if all goes well, you will only have to wait a bit for the data synchronization process to complete. This may take a long time if you have a large Zotero library.
Kerko's data will be stored in the instance
subdirectory.
KerkoApp should launch once the synchronization process has completed. When you see the following message in the terminal, proceed to the next step:
[INFO] Listening at: http://0.0.0.0:80\n
Open http://localhost:8080/ in your browser and explore the bibliography!
To stop the KerkoApp server, press Ctrl+C in the terminal where the container is running.
The next time you execute make run
, it will find that the image has been already been downloaded and the data synchronized, and thus it will just launch the server.
Using the Kerko command line interface (CLI) with Docker
To use Kerko's command line interface, enter this command from the same directory as Makefile
:
make shell\n
This will start an interactive shell within the Docker container. From there, you may run Kerko commands to clean Kerko's data, to synchronize from zotero.org, or to check Kerko's configuration. The command below lists all the commands provided by Kerko:
flask kerko --help\n
To exit the interactive shell, enter exit
or press Ctrl+D at the command prompt.
Building a Docker image for production
The Makefile
is just an example that shows how to build and interact with a dockerized KerkoApp. For production use, you might want to clone the full KerkoApp repository, make some changes to its Dockerfile
, and build your own image.
For full documentation on how to run Docker containers, including port mapping and volume binding, see the Docker documentation.
"},{"location":"getting-started/#creating-a-custom-application","title":"Creating a custom application","text":"This section should help you understand the minimal steps required for setting up Kerko within a custom Flask application.
Tip
For a ready-to-use standalone application, you will be better off using KerkoApp instead.
Some familiarity with Flask should help you make more sense of the instructions, but should not be absolutely necessary for getting them to work. Let's now build a minimal app:
Create an empty directory myapp
where your application reside.
Install Kerko in a new virtual environment:
POSIXWindowscd myapp\npython -m venv venv\nsource venv/bin/activate\npip install kerko\n
cd myapp\npython -m venv venv\nvenv\\Scripts\\activate.bat\npip install kerko\n
In the myapp
directory, create a file named .env
, where parameters required by Kerko will be configured, with content such as the example below:
MYAPP_SECRET_KEY=\"your-random-secret-key\"\nMYAPP_ZOTERO_API_KEY=\"xxxxxxxxxxxxxxxxxxxxxxxx\"\nMYAPP_ZOTERO_LIBRARY_ID=\"9999999\"\nMYAPP_ZOTERO_LIBRARY_TYPE=\"group\"\n
Replace each value with a proper one. The meaning of each parameter is outlined below:
MYAPP_SECRET_KEY
: This parameter is required for generating secure tokens in web forms. It should have a hard to guess value, and should really remain secret. For this reason, never add your .env
file to a code repository.MYAPP_ZOTERO_API_KEY
: Your Zotero API key. See API key creation instructions.MYAPP_ZOTERO_LIBRARY_ID
: The identifier of the Zotero library to get data from. For a personal library the value is your userID, as found on https://www.zotero.org/settings/keys (you must be logged-in). For a group library this value is the groupID of the library, as found in the URL of the library (e.g., the groupID of the library at https://www.zotero.org/groups/2348869/kerko_demo is \"2348869\"
).MYAPP_ZOTERO_LIBRARY_TYPE
: The type of library to get data from, either \"user\"
for a personal library, or \"group\"
for a group library.A .env
file is a good place to store an application's secrets. It is good practice to keep this file only on the machine where the application is hosted, and to never push it to a code repository.
Create a file named wsgi.py
with the following content:
import kerko\nfrom flask import Flask\nfrom flask_babel import Babel\nfrom flask_bootstrap import Bootstrap4\nfrom kerko.composer import Composer\nfrom kerko.config_helpers import config_set, config_update, validate_config\n\napp = Flask(__name__)\n
The above imports required modules and creates the Flask application object (app
). Then, load the default Kerko configuration, and update it from values set in .env
:
# Initialize app configuration with Kerko's defaults.\nconfig_update(app.config, kerko.DEFAULTS)\n\n# Update app configuration from environment variables.\napp.config.from_prefixed_env(prefix=\"MYAPP\")\n
Next, adjust general application parameters to your liking. For example, we can use the config_set
function to set the main title of the web application to \"My App\"
. This function can be called each time you wish to set a configuration option.
# Make changes to the Kerko configuration here, if desired.\nconfig_set(app.config, \"kerko.meta.title\", \"My App\")\n
Next, have Kerko parse and validate the configuration. Then create the kerko_composer
object, which provides key elements needed by Kerko such as the fields to display and search, and the facets made available for filtering:
# Validate configuration and save its parsed version.\nparse_config(app.config)\n\n# Initialize the Composer object.\napp.config[\"kerko_composer\"] = Composer(app.config)\n\n# Make changes to the Kerko composer object here, if desired.\n
Using methods of the Composer
class, your application could alter the kerko_composer
object if needed, to add, remove or alter fields, facets, sort options, search scopes, record download formats, or badges.
Finally, initialize extensions required by Kerko (see the respective documentations of Flask-Babel and Bootstrap-Flask for more details), and register the Kerko blueprint with the application object:
wsgi.pybabel = Babel(app)\nbootstrap = Bootstrap4(app)\n\napp.register_blueprint(kerko.make_blueprint(), url_prefix=\"/bibliography\")\n
The url_prefix
argument given above defines the base path for every URL provided by Kerko.
Note
The full code example is available on GitHub.
In the same directory as wsgi.py
with your virtual environment active, run the following shell commands:
flask --debug kerko sync\n
If you have a large Zotero library and/or large file attachments, that command may take a while to complete. Wait until the command finishes. In production use, this command is usually added to the crontab file for regular execution.
The --debug
switch is optional. If you use it, some messages will give you an idea of the sync process' progress. If you omit it, the command will run silently unless there are warnings or errors.
To list all commands provided by Kerko:
flask kerko --help\n
Run your application:
flask --debug run\n
Open http://127.0.0.1:5000/bibliography/ in your browser and explore the bibliography!
You have just built a really minimal application for Kerko. However, if you are looking at developing a custom Kerko application, we recommend that you still look at KerkoApp for a more advanced starting point. While still small, KerkoApp adds some structure as well as features such as TOML configuration files, translations loading, a syslog logging handler, and error pages.
"},{"location":"localization/","title":"Localization","text":"This section is about adapting Kerko for specific regions or languages. For this purpose, the main issues to consider are:
BABEL_DEFAULT_LOCALE
. If no translation is available for the desired language, or if the existing translation needs to be updated, see Translating Kerko and Translating KerkoApp below.BABEL_DEFAULT_TIMEZONE
.kerko.zotero.locale
.kerko.search.whoosh_language
.Kerko translations are managed with Babel.
The following commands should be executed from the root Kerko directory (the one that contains babel.cfg
), and the virtual environment must have been activated beforehand.
Create or update the PO template (POT) file. Replace CURRENT_VERSION
with the current Kerko version:
pybabel extract -F babel.cfg -o src/kerko/translations/kerko.pot --project=Kerko --version=CURRENT_VERSION --copyright-holder=\"Kerko Contributors\" src/kerko\n
Create a new PO file (for a new locale) based on the POT file. Replace YOUR_LOCALE
with the appropriate language code, e.g., de
, es
, fr
:
pybabel init -l YOUR_LOCALE -D kerko -i src/kerko/translations/kerko.pot -d src/kerko/translations\n
Update an existing PO file based on the POT file:
pybabel update -l YOUR_LOCALE -D kerko -i src/kerko/translations/kerko.pot -d src/kerko/translations\n
Compile MO files:
pybabel compile -l YOUR_LOCALE -D kerko -d src/kerko/translations --statistics\n
Contributing your translation
You are welcome to contribute your translation. See Submitting a translation. It is only thanks to user contributions that Kerko is available in multiple languages.
"},{"location":"localization/#translating-kerkoapp","title":"Translating KerkoApp","text":"Although most user interface messages come from Kerko, KerkoApp also has messages of its own, and thus its own separate translation file.
KerkoApp translations are managed with Babel.
The following commands should be executed from the root KerkoApp directory (the one that contains babel.cfg
), and the virtual environment must have been activated beforehand.
Create or update the PO file template (POT). Replace CURRENT_VERSION
with your current KerkoApp version:
pybabel extract -F babel.cfg -o kerkoapp/translations/messages.pot --project=KerkoApp --version=CURRENT_VERSION --copyright-holder=\"Kerko Contributors\" kerkoapp\n
Create a new PO file (for a new locale) based on the POT file. Replace YOUR_LOCALE
with the appropriate language code, e.g., de
, es
, it
:
pybabel init -l YOUR_LOCALE -i kerkoapp/translations/messages.pot -d kerkoapp/translations\n
Update an existing PO file based on the POT file:
pybabel update -l YOUR_LOCALE -i kerkoapp/translations/messages.pot -d kerkoapp/translations\n
Compile MO files:
pybabel compile -l YOUR_LOCALE -d kerkoapp/translations\n
"},{"location":"synchronization/","title":"Synchronization","text":"Kerko synchronizes its data from Zotero through a 3-step process:
The first step is an incremental update of the cache, which is a local copy of the library. To this end, Kerko uses the Zotero API to request items and collections from the library on zotero.org. Unless the library is getting synchronized for the first time by Kerko, this will only request new and changed items from Zotero in order to reduce the number of API requests.
The second step reads data from the cache to update the search index. If the cache has changed since the last update, a full update of the search index is performed. No Zotero API calls are made during this step. Any changes to the search index are only committed at the end of this step, thus while the update is taking place users still see the data as it was prior to the synchronization run.
The third and last step reads the list of file attachments from the search index, with their MD5 hashes. It compares the hashes with those of the available local copies of the files, and downloads new or changed files from Zotero. It also deletes any local files that may no longer be used.
Usually, all synchronization steps should be executed. But under certain circumstances it can be useful to run a specific step alone. For example, after changing certain configuration settings, instead of cleaning all data and performing a lengthy full synchronization from Zotero, one may clean just the search index and rebuild it from the cache.
Note
The synchronization process is unidirectional, where Kerko pulls data from Zotero. Kerko will never try to write anything to your Zotero library.
"},{"location":"synchronization/#command-line-interface-cli","title":"Command line interface (CLI)","text":"Kerko provides an integration with the Flask command line interface. The flask
command will work with your virtual environment active.
Before running a command, go to the application's directory (where the wsgi.py
file is found). That is the easiest way to help Flask discover the application.
Some frequently used commands are:
flask kerko --help
Lists all commands provided by Kerko.
flask kerko sync
Synchronizes everything: the cache (from Zotero), the search index (from the cache), the attachments (from files in Zotero, based on list in search index).
Tip: Making commands more verbose
The --debug
option may be used with any Flask command and will cause Kerko to output more information. It will tell quite a bit more about what is happening during the synchronization process. For example:
flask --debug kerko sync\n
flask kerko sync --help
Shows help specifically about the sync
command:
flask kerko sync index
Synchronizes just the search index (from the cache).
flask kerko sync cache --full
When possible, the synchronization process performs an incremental update of just the new or changed items. Here, the --full
option forces a full synchronization of the cache, even if no or just some items have been updated since the last synchronization of the cache.
This can be useful after changing certain configuration parameters.
flask kerko clean everything
Deletes all of Kerko's data: cache, search index, attachments.
flask kerko clean --help
Shows help about the clean command.
flask kerko clean cache
Deletes just the cache. A subsequent execution of flask kerko sync
will perform a full update from Zotero, but it will not re-download all file attachments.
This does not affect the search index. Thus, if the index was built before a clean cache
, users will still be able to access the bibliography using the Kerko web interface.
flask kerko clean index
Deletes just the search index. The bibliography will become unavailable to the Kerko web interface until the index gets synchronized again.
It can be necessary to use this command after changing certain configuration parameters, and you will usually want to run flask kerko sync index
immediately after.
flask kerko config
Output a consolidated view of all configuration parameters, from all of your configuration files, and including the defaults provided by Kerko that you may not have explicitly configured.
"},{"location":"synchronization/#monitoring-data-synchronization","title":"Monitoring data synchronization","text":"Kerko provides a web API endpoint that you could use to monitor data synchronization.
In the description below, BASE_URL
should be replaced with the protocol, domain, port, and Kerko URL path prefix that are relevant to your installation, e.g., https://example.com/bibliography
.
The web API endpoint is:
BASE_URL/api/last-sync
Returns a JSON object with information about the last synchronization from Zotero. If no sync has been performed yet, it returns an empty JSON object, otherwise the returned object contains the following values:
hours_ago
Number of hours since the last sync.
when
ISO 8601 date string with the date and time of the last sync.
Sample JSON output{\n \"hours_ago\": 17.029,\n \"when\": \"2023-05-24T11:10:29.093335-04:00\"\n}\n
"},{"location":"troubleshooting/","title":"Troubleshooting","text":""},{"location":"troubleshooting/#no-such-command-kerko-error-when-running-flask","title":"No such command \"kerko\" error when running Flask","text":"Make sure to run the flask
command from the application's directory (where the wsgi.py
file is found).
To run it from other directories, you could use the --app
option, or to set the FLASK_APP
environment variable. See application discovery for details.
For example:
flask --app=/path/to/kerkoapp/wsgi:app kerko sync\n
"},{"location":"troubleshooting/#configuration-parameter-change-has-no-effect","title":"Configuration parameter change has no effect","text":"Restart the application. This is required for any configuration change to take effect.
If the change still appears to have no effect after a restart, use the following command to verify that the desired parameter value is actually being used:
flask --debug kerko config\n
If the parameter's value is not the expected one, check your configuration files. If you are uncertain about which configuration files are being loaded by the application, check the first few lines printed by the above command; these list the TOML files in their loading order. Remember that a later file can override values set in a previous one. If you are still unable to trace the source of an incorrect parameter value, check your environment variables. Environment variables can override parameter values set in TOML configuration files.
If, on the other hand, the parameter's value is the desired one, then review the documentation for that parameter. Make sure you understand the effect of the parameter value, and check for any notes or warnings. Some parameters require a rebuild of the cache or the search index to become effective.
"},{"location":"troubleshooting/#custom-application-conflicting-package-versions-with-standard-installation","title":"Custom application: Conflicting package versions with standard installation","text":"The requirements/run.txt
file specifies a precise version for each required package, ensuring consistent results with the last environment KerkoApp was tested with. If some of these packages are already present in your Python environment, their versions are likely to be different and some Python code outside KerkoApp might require those versions. In that case, try replacing run.txt
with run.in
in the install command:
pip install -r requirements/run.in\n
Requirements in run.in
are more flexible regarding the versions. If you still have version conflicts with those requirements, you'll have to find out which version to use, checking that it is compatible with both KerkoApp and your other Python code.
Before attempting any upgrade, it is highly recommended that you do a backup of all of your code, configuration files, data files, and Python virtual environment.
"},{"location":"upgrading/#from-10x-to-11x-or-12x","title":"From 1.0.x to 1.1.x or 1.2.x","text":""},{"location":"upgrading/#kerkoapp","title":"KerkoApp","text":"The instructions below make the assumption that you have cloned KerkoApp from its Git repository.
Get the desired version of KerkoApp. You may check the list of available versions. For version 1.1.0, for example, replace VERSION
with 1.1.0
in the command below:
git fetch && git checkout VERSION\n
Activate your Python virtual environment.
Install Python dependencies:
pip install --force-reinstall -r requirements/run.txt\n
Adapt your configuration file:
kerko.feeds.fields
parameter is either omitted or has at least the following values: [\"id\", \"data\", \"item_fields\"]
.Rebuild your search index using the following commands:
flask kerko clean index\nflask kerko sync index\n
Restart the application.
If you have a custom application, the following changes will need to be applied:
The application is now responsible for instantiating the blueprint by calling kerko.make_blueprint()
. Any previous uses of the global kerko.blueprint
object must be replaced, as Kerko no longer provides it. If registration was your application's only use of that object, the change could look like:
app.register_blueprint(kerko.blueprint, url_prefix='/bibliography')\n
Afterapp.register_blueprint(kerko.make_blueprint(), url_prefix='/bibliography')\n
... where app
is the Flask
object.
Version 1.0.x brings significant changes on how Kerko can be configured. Before you attempt an upgrade, reading Configuration basics is a must.
"},{"location":"upgrading/#kerkoapp_1","title":"KerkoApp","text":"The instructions below make the assumption that you have cloned KerkoApp from its Git repository.
Rename the default branch of your local KerkoApp repository:
git branch -m master main\ngit fetch origin\ngit branch -u origin/main main\ngit remote set-head origin -a\n
Get the desired version of KerkoApp. You may check the list of available versions. For version 1.0.0, for example, replace VERSION
with 1.0.0
in the command below:
git checkout VERSION\n
Activate your Python virtual environment.
Install Python dependencies:
pip install --force-reinstall -r requirements/run.txt\n
Rename the .env
file to dotenv.old
. We no longer want KerkoApp to use that file, but it might be useful to keep it as reference while we migrate the configuration.
.secrets.toml
and config.toml
, in the KerkoApp directory, i.e., the directory where wsgi.py
is found.SECRET_KEY
and KERKO_ZOTERO_API_KEY
lines from dotenv.old
into .secrets.toml
. In .secrets.toml
, rename the KERKO_ZOTERO_API_KEY
parameter to ZOTERO_API_KEY
. For each of the two parameters, make sure the value following the equal sign (=
) is surrounded by double quotes (\"
). To ascertain the syntax, you may have a look at the sample.secrets.toml
file provided by KerkoApp.dotenv.old
to config.toml
. For each parameter, use the list below to determine if something special needs to be done to migrate it. Almost all configuration parameters have been renamed and/or moved into a hierarchical structure (indicated by an arrow (\u2192)). Check the parameter values too as the syntax of a TOML file is slightly different from that of a .env
file, e.g., in TOML string values must be surrounded by double quotes (\"
), and booleans values must be either true
or false
(lowercase, no quotes). Refer to the parameters documentation for additional information, and have a look at the sample.config.toml
file provided by KerkoApp.DEBUG
: Remove. Debug mode is now activated with the --debug
command line option.FLASK_APP
: Probably not needed anymore. In doubt, please refer to the Flask documentation on application discovery. If you do need this variable, then a .env
file could be the right place. It will not work from a TOML file. Note also that the application is now referenced as wsgi.app
instead of kerkoapp.app
.FLASK_ENV
: Remove. Flask 2.3 stopped supporting it. Debug mode is now activated with the --debug
command line option.KERKO_BOOTSTRAP_VERSION
\u2192 kerko.assets.bootstrap_version
KERKO_CSL_STYLE
\u2192 kerko.zotero.csl_style
KERKO_COMPOSER
\u2192 kerko_composer
KERKO_DATA_DIR
\u2192 DATA_PATH
. Now optional, relative to the instance path, and defaulting to kerko
instead of data/kerko
.KERKO_DOWNLOAD_ATTACHMENT_NEW_WINDOW
\u2192 kerko.features.download_attachment_new_window
KERKO_DOWNLOAD_CITATIONS_LINK
\u2192 kerko.features.download_results
KERKO_DOWNLOAD_CITATIONS_MAX_COUNT
\u2192 kerko.features.download_results_max_count
KERKO_FEEDS
\u2192 kerko.feeds.formats
KERKO_FEEDS_FIELDS
\u2192 kerko.feeds.fields
KERKO_FEEDS_MAX_DAYS
\u2192 kerko.feeds.max_days
KERKO_FEEDS_REJECT_ANY
\u2192 kerko.feeds.reject_any
KERKO_FEEDS_REQUIRE_ANY
\u2192 kerko.feeds.require_any
KERKO_FULLTEXT_SEARCH
\u2192 kerko.search.fulltext
KERKO_HIGHWIREPRESS_TAGS
\u2192 kerko.meta.highwirepress_tags
KERKO_JQUERY_VERSION
\u2192 kerko.assets.jquery_version
KERKO_PAGE_LEN
\u2192 kerko.pagination.page_len
KERKO_PAGER_LINKS
\u2192 kerko.pagination.pager_links
KERKO_POPPER_VERSION
\u2192 kerko.assets.popper_version
KERKO_PRINT_CITATIONS_LINK
\u2192 kerko.features.print_results
KERKO_PRINT_CITATIONS_MAX_COUNT
\u2192 kerko.features.print_results_max_count
KERKO_PRINT_ITEM_LINK
\u2192 kerko.features.print_item
KERKO_RELATIONS_INITIAL_LIMIT
\u2192 kerko.features.relations_initial_limit
KERKO_RELATIONS_LINKS
\u2192 kerko.features.relations_links
KERKO_RELATIONS_SORT
\u2192 kerko.features.relations_sort
KERKO_RESULTS_ABSTRACTS
\u2192 kerko.features.results_abstracts
KERKO_RESULTS_ABSTRACTS_MAX_LENGTH
\u2192 kerko.features.results_abstracts_max_length
KERKO_RESULTS_ABSTRACTS_MAX_LENGTH_LEEWAY
\u2192 kerko.features.results_abstracts_max_length_leeway
KERKO_RESULTS_ABSTRACTS_TOGGLER
\u2192 kerko.features.results_abstracts_toggler
KERKO_RESULTS_ATTACHMENT_LINKS
\u2192 kerko.features.results_attachment_links
KERKO_RESULTS_FIELDS
\u2192 kerko.search.result_fields
KERKO_RESULTS_URL_LINKS
\u2192 kerko.features.results_url_links
KERKO_TEMPLATE_ATOM_FEED
\u2192 kerko.templates.atom_feed
KERKO_TEMPLATE_BASE
\u2192 kerko.templates.base
KERKO_TEMPLATE_ITEM
\u2192 kerko.templates.item
KERKO_TEMPLATE_LAYOUT
\u2192 kerko.templates.layout
KERKO_TEMPLATE_SEARCH
\u2192 kerko.templates.search
KERKO_TEMPLATE_SEARCH_ITEM
\u2192 kerko.templates.search_item
KERKO_TITLE
\u2192 kerko.meta.title
KERKO_USE_TRANSLATIONS
: Remove.KERKO_WHOOSH_LANGUAGE
\u2192 kerko.search.whoosh_language
KERKO_WITH_JQUERY
\u2192 kerko.assets.with_jquery
KERKO_WITH_POPPER
\u2192 kerko.assets.with_popper
KERKO_ZOTERO_API_KEY
\u2192 ZOTERO_API_KEY
KERKO_ZOTERO_BATCH_SIZE
\u2192 kerko.zotero.batch_size
KERKO_ZOTERO_LIBRARY_ID
\u2192 ZOTERO_LIBRARY_ID
KERKO_ZOTERO_LIBRARY_TYPE
\u2192 ZOTERO_LIBRARY_TYPE
KERKO_ZOTERO_LOCALE
\u2192 kerko.zotero.locale
KERKO_ZOTERO_MAX_ATTEMPTS
\u2192 kerko.zotero.max_attempts
KERKO_ZOTERO_WAIT
\u2192 kerko.zotero.wait
KERKOAPP_CHILD_EXCLUDE_RE
\u2192 kerko.zotero.child_exclude_re
KERKOAPP_CHILD_INCLUDE_RE
\u2192 kerko.zotero.child_include_re
KERKOAPP_COLLECTION_FACETS
\u2192 kerko.facets.*
. See sub-parameters type
(set it to \"collection\"
), collection_key
, weight
, and title
.KERKOAPP_EXCLUDE_DEFAULT_BADGES
: Remove. There is no replacement since Kerko does not provide any default badges at this point.KERKOAPP_EXCLUDE_DEFAULT_CITATION_FORMATS
\u2192 kerko.citation_formats.*
. See sub-parameter enable
.KERKOAPP_EXCLUDE_DEFAULT_FACETS
\u2192 kerko.facets.*
. See sub-parameter enable
.KERKOAPP_EXCLUDE_DEFAULT_FIELDS
\u2192 kerko.search_fields.*
. See sub-parameter enable
.KERKOAPP_EXCLUDE_DEFAULT_SCOPES
\u2192 kerko.scopes.*
. See sub-parameter enable
.KERKOAPP_EXCLUDE_DEFAULT_SORTS
\u2192 kerko.sorts.*
. See sub-parameter enable
.KERKOAPP_FACET_INITIAL_LIMIT_LEEWAY
\u2192 kerko.facets.*.initial_limit_leeway
. This is now set individually for each facet, and there is no longer a global parameter.KERKOAPP_FACET_INITIAL_LIMIT
\u2192 kerko.facets.*.initial_limit
. This is now set individually for each facet, and there is no longer a global parameter.KERKOAPP_ITEM_EXCLUDE_RE
\u2192 kerko.zotero.item_exclude_re
KERKOAPP_ITEM_INCLUDE_RE
\u2192 kerko.zotero.item_include_re
KERKOAPP_MIME_TYPES
\u2192 kerko.zotero.attachment_mime_types
KERKOAPP_TAG_EXCLUDE_RE
\u2192 kerko.zotero.tag_exclude_re
KERKOAPP_TAG_INCLUDE_RE
\u2192 kerko.zotero.tag_include_re
PROXY_FIX
\u2192 kerkoapp.proxy_fix.*
kerko.link_groups.navbar
parameter (see the parameters documentation for details).DATA_PATH
nor the INSTANCE_PATH
parameters, then rename KerkoApp's data
directory to instance
.wsgi.app
(or wsgi:app
) instead of kerkoapp.app
(or kerkoapp:app
).Rebuild your search index using the following commands:
flask kerko clean index\nflask kerko sync index\n
Restart the application.
Occurrences of parameter names in custom templates will need to be edited. For example:
config.KERKO_COMPOSER
\u2192 config.kerko_composer
config.KERKO_TITLE
\u2192 config.kerko.meta.title
The following item fields have been renamed. Occurrences of these in your templates will need to be edited:
z_dateAdded
\u2192 date_added
z_dateModified
\u2192 date_modified
The following views have been renamed. Occurrences of these in your templates (perhaps in calls to url_for
) will need to be edited:
item_citation_download
\u2192 item_bib_download
search_citation_download
\u2192 search_bib_download
Configuration initialization and loading has greatly changed. If you have a custom application, it will need to be adapted even if you do not plan to use TOML files. See Creating a custom application for a working example, and refer to the changelog for other breaking changes.
"}]} \ No newline at end of file diff --git a/development/sitemap.xml.gz b/development/sitemap.xml.gz index d7a42a5..0ebf654 100644 Binary files a/development/sitemap.xml.gz and b/development/sitemap.xml.gz differ