You are senior full-stack software engineer with 20 years of experience writing web apps. You have been working with the Svelte web development framework for 8 years, since it was first released, and you currently are a leading expert on Svelte 5 and SvelteKit 2. Additionally, you are a pioneer developer on the Nostr protocol, and have developing production-quality Nostr apps for 4 years.
## Project Overview
Alexandria is a Nostr project written in Svelte 5 and SvelteKit 2. It is a web app for reading, commenting on, and publishing books, blogs, and other long-form content stored on Nostr relays. It revolves around breaking long AsciiDoc documents into Nostr events, with each event containing a paragraph or so of text from the document. These individual content events are organized by index events into publications. An index contains an ordered list of references to other index events or content events, forming a tree.
### Reader Features
In reader mode, Alexandria loads a document tree from a root publication index event. The AsciiDoc text content of the various content events, along with headers specified by tags in the index events, is composed and rendered as a single document from the user's point of view.
### Tech Stack
Svelte components in Alexandria use TypeScript exclusively over plain JavaScript. Styles are defined via Tailwind 4 utility classes, and some custom utility classes are defined in [app.css](mdc:src/app.css). The app runs on Deno, but maintains compatibility with Node.js.
## General Guidelines
When responding to prompts, adhere to the following rules:
- Avoid making apologetic or conciliatory statements.
- Avoid verbose responses; be direct and to the point.
- Provide links to relevant documentation so that I can do further reading on the tools or techniques discussed and used in your responses.
- When I tell you a response is incorrect, avoid simply agreeing with me; think about the points raised and provide well-reasoned explanations for your subsequent responses.
- Avoid proposing code edits unless I specifically tell you to do so.
- When giving examples from my codebase, include the file name and line numbers so I can find the relevant code easily.
## Code Style
Observe the following style guidelines when writing code:
### General Guidance
- Use PascalCase names for Svelte 5 components and their files.
- Use snake_case names for plain TypeScript files.
- Use comments sparingly; code should be self-documenting.
### JavaScript/TypeScript
- Use an indentation size of 2 spaces.
- Use camelCase names for variables, classes, and functions.
- Give variables, classes, and functions descriptive names that reflect their content and purpose.
- Use Svelte 5 features, such as runes. Avoid using legacy Svelte 4 features.
- Write JSDoc comments for all functions.
- Use blocks enclosed by curly brackets when writing control flow expressions such as `for` and `while` loops, and `if` and `switch` statements.
- Begin `case` expressions in a `switch` statement at the same indentation level as the `switch` itself. Indent code within a `case` block.
- Limit line length to 100 characters; break statements across lines if necessary.
Alexandria is a reader and writer for <Ahref="/publication?d=gitcitadel-project-documentation-curated-publications-specification-7-by-stella-v-1">curated publications</A> (in Asciidoc), wiki pages (Asciidoc), and will eventually also support long-form articles (Markdown). It is produced by the <Ahref="/publication?d=gitcitadel-project-documentation-gitcitadel-project-1-by-stella-v-1">GitCitadel project team</A>.
> (in Asciidoc), wiki pages (Asciidoc), and will eventually also support long-form
Please submit support issues on the <Ahref="https://gitcitadel.com/r/naddr1qvzqqqrhnypzquqjyy5zww7uq7hehemjt7juf0q0c9rgv6lv8r2yxcxuf0rvcx9eqy88wumn8ghj7mn0wvhxcmmv9uq3wamnwvaz7tmjv4kxz7fwdehhxarj9e3xzmny9uqsuamnwvaz7tmwdaejumr0dshsqzjpd3jhsctwv3exjcgtpg0n0/issues"target="_blank">Alexandria repo page</A> and follow us on <Ahref="https://github.com/ShadowySupercode/gitcitadel"target="_blank">GitHub</A> and <Ahref="https://geyser.fund/project/gitcitadel"target="_blank">Geyserfund</A>.
We are easiest to contact over our Nostr address <Ahref="https://njump.me/nprofile1qqsggm4l0xs23qfjwnkfwf6fqcs66s3lz637gaxhl4nwd2vtle8rnfqprfmhxue69uhhg6r9vehhyetnwshxummnw3erztnrdaks5zhueg"title="npub1s3ht77dq4zqnya8vjun5jp3p44pr794ru36d0ltxu65chljw8xjqd975wz"target="_blank">npub1s3h…75wz</A>.
Alexandria opens up to the <Ahref="./">landing page</A>, where the user can: login (top-right), select whether to only view the publications hosted on the <Ahref="https://thecitadel.nostr1.com/"target="_blank">thecitadel document relay</A> or add in their own relays, and scroll/search the publications.
There is also the ability to view the publications as a diagram, if you click on "Visualize", and to publish an e-book or other document (coming soon).
We are easiest to contact over our Nostr address <A
If you click on a card, which represents a 30040 index event, the associated reading view opens to the publication. The app then pulls all of the content events (30041s and 30818s for wiki pages), in the order in which they are indexed, and displays them as a single document.
Each content section (30041 or 30818) is also a level in the table of contents, which can be accessed from the floating icon top-left in the reading view. This allows for navigation within the publication. (This functionality has been temporarily disabled.)
</P>
<Pclass="mb-4">
Alexandria opens up to the <Ahref="./">landing page</A>, where the user
The most common use for Alexandria is for e-books: both those users have written themselves and those uploaded to Nostr from other sources. The first minor version of the app, Gutenberg, is focused on displaying and producing these publications.
class="image-border rounded-lg"
</P>
width="400"
/>
<Pclass="mb-3">
<Img
An example of a book is <Ahref="/publication?d=jane-eyre-an-autobiography-by-charlotte-bront%C3%AB-v-3rd-edition">Jane Eyre</A>
src="/screenshots/YourRelays.png"
</P>
alt="Relay selection"
class="image-border rounded-lg"
<divclass="flex justify-center my-4">
width="400"
<Imgsrc="/screenshots/JaneEyre.png"alt="Jane Eyre, by Charlotte Brontë"class='image-border rounded-lg'width="400"/>
There is also the ability to view the publications as a diagram, if you
<Pclass="mb-3">
click on "Visualize", and to publish an e-book or other document (coming
Alexandria will also display research papers with Asciimath and LaTeX embedding, and the normal advanced formatting options available for Asciidoc. In addition, we will be implementing special citation events, which will serve as an alternative or addition to the normal footnotes.
soon).
</P>
</P>
<Pclass="mb-3">
<Pclass="mb-3">
Correctly displaying such papers, integrating citations, and allowing them to be reviewed (with kind 1111 comments), and annotated (with highlights) by users, is the focus of the second minor version, Euler.
If you click on a card, which represents a 30040 index event, the
</P>
associated reading view opens to the publication. The app then pulls all
of the content events (30041s and 30818s for wiki pages), in the order in
<Pclass="mb-3">
which they are indexed, and displays them as a single document.
Euler will also pioneer the HTTP-based (rather than websocket-based) e-paper compatible version of the web app.
</P>
</P>
<Pclass="mb-3">
<Pclass="mb-3">
Each content section (30041 or 30818) is also a level in the table of
An example of a research paper is <Ahref="/publication?d=less-partnering-less-children-or-both-by-j.i.s.-hellstrand-v-1">Less Partnering, Less Children, or Both?</A>
contents, which can be accessed from the floating icon top-left in the
</P>
reading view. This allows for navigation within the publication. (This
Our own team uses Alexandria to document the app, to display our <Ahref="/publication?d=the-gitcitadel-blog-by-stella-v-1">blog entries</A>, as well as to store copies of our most interesting <Ahref="/publication?d=gitcitadel-project-documentation-by-stella-v-1">technical specifications</A>.
<Headingtag='h3'class='h-leather mb-3'>For wiki pages</Heading>
/>
</div>
<Pclass="mb-3">
Alexandria now supports wiki pages (kind 30818), allowing for collaborative knowledge bases and documentation. Wiki pages use the same Asciidoc format as other publications but are specifically designed for interconnected, evolving content.
<Headingtag="h2"class="h-leather mt-4 mb-2">Typical use cases</Heading>
Wiki pages can be linked to from other publications and can contain links to other wiki pages, creating a web of knowledge that can be navigated and explored.
<Pclass="mb-3">
</P>
The most common use for Alexandria is for e-books: both those users have
written themselves and those uploaded to Nostr from other sources. The
</main>
first minor version of the app, Gutenberg, is focused on displaying and
import Article from "$lib/components/Publication.svelte";
import Publication from "$lib/components/Publication.svelte";
import {TextPlaceholder} from "flowbite-svelte";
import {TextPlaceholder} from "flowbite-svelte";
import type {PageData} from "./$types";
import type {PageProps} from "./$types";
import {onDestroy} from "svelte";
import {onDestroy,setContext} from "svelte";
import type {NDKEvent} from "@nostr-dev-kit/ndk";
import {PublicationTree} from "$lib/data_structures/publication_tree";
import {pharosInstance} from "$lib/parser";
import Processor from "asciidoctor";
import {page} from "$app/stores";
// Extend the PageData type with the properties we need
let {data}: PageProps = $props();
interface ExtendedPageData extends PageData {
waitable: Promise<any>;
publicationType: string;
indexEvent: NDKEvent;
parser: any;
}
let {data} = $props<{data: ExtendedPageData}>();
const publicationTree = new PublicationTree(data.indexEvent, data.ndk);
setContext('publicationTree', publicationTree);
setContext('asciidoctor', Processor());
// Get publication metadata for OpenGraph tags
// Get publication metadata for OpenGraph tags
let title = $derived(data.indexEvent?.getMatchingTags('title')[0]?.[1] || data.parser?.getIndexTitle(data.parser?.getRootIndexId()) || 'Alexandria Publication');
let title = $derived(data.indexEvent?.getMatchingTags('title')[0]?.[1] || data.parser?.getIndexTitle(data.parser?.getRootIndexId()) || 'Alexandria Publication');
let currentUrl = $page.url.href;
let currentUrl = data.url?.href ?? '';
// Get image and summary from the event tags if available
// Get image and summary from the event tags if available
// If image unavailable, use the Alexandria default pic.
// If image unavailable, use the Alexandria default pic.
let image = $derived(data.indexEvent?.getMatchingTags('image')[0]?.[1] || '/screenshots/old_books.jpg');
let image = $derived(data.indexEvent?.getMatchingTags('image')[0]?.[1] || '/screenshots/old_books.jpg');
let summary = $derived(data.indexEvent?.getMatchingTags('summary')[0]?.[1] || 'Alexandria is a digital library, utilizing Nostr events for curated publications and wiki pages.');
let summary = $derived(data.indexEvent?.getMatchingTags('summary')[0]?.[1] || 'Alexandria is a digital library, utilizing Nostr events for curated publications and wiki pages.');