> One deficiency you can see is that it’s impossible to generate a “previous page” link
It is perfectly possible to have a "previous page" link. Your pagination needs to support "before" cursor semantic, allowing a consumer to retrieve the N items before the row identified by the cursor.
It is also possible to create a "next page". You only need to take your current page's last id and use it in your query like "where id > current_last_element_id".
"first page" and "last page" are possible as well, simply do "where id > 0" for first and "where id <= (subselect max id)".
You may need to invert order here and there, but it is perfectly possible to use cursor base pagination in a GUI as long as you don't need to provide jumping to a specific page number.
It is perfectly possible to have a "previous page" link. Your pagination needs to support "before" cursor semantic, allowing a consumer to retrieve the N items before the row identified by the cursor.