(null)
- const [loading, setLoading] = useState(false)
useEffect(() => {
const check = async () => {
if (!connected || !pubkey) {
setPresentation(null)
- setLoading(false)
return
}
- setLoading(true)
+ // Check for presentation asynchronously, but don't show loading state
const pres = await checkPresentationExists()
setPresentation(pres)
- setLoading(false)
}
void check()
}, [connected, pubkey, checkPresentationExists])
@@ -85,14 +74,11 @@ export function ConditionalPublishButton() {
return
}
- if (loading) {
- return
+ // If presentation exists, show author profile link with image/fallback
+ if (presentation) {
+ return
}
- if (!presentation) {
- return
- }
-
- // If presentation exists, show author profile link instead of publish button
- return
+ // Otherwise, show create author page button immediately (no loading state)
+ return
}
diff --git a/components/DocsContent.tsx b/components/DocsContent.tsx
index 8ddafcb..8c0fd12 100644
--- a/components/DocsContent.tsx
+++ b/components/DocsContent.tsx
@@ -1,5 +1,5 @@
-import React from 'react'
import { renderMarkdown } from '@/lib/markdownRenderer'
+import { t } from '@/lib/i18n'
interface DocsContentProps {
content: string
@@ -10,7 +10,7 @@ export function DocsContent({ content, loading }: DocsContentProps) {
if (loading) {
return (
-
Chargement de la documentation...
+
{t('docs.loading')}
)
}
diff --git a/components/Nip95ConfigManager.tsx b/components/Nip95ConfigManager.tsx
index cc32a95..770ccd2 100644
--- a/components/Nip95ConfigManager.tsx
+++ b/components/Nip95ConfigManager.tsx
@@ -219,13 +219,13 @@ export function Nip95ConfigManager({ onConfigChange }: Nip95ConfigManagerProps)
setEditingId(api.id)}
- title="Click to edit URL"
+ title={t('settings.nip95.list.editUrl')}
>
{api.url}
)}
- Priority: {api.priority} | ID: {api.id}
+ {t('settings.nip95.list.priorityLabel', { priority: api.priority, id: api.id })}
@@ -273,11 +273,10 @@ export function Nip95ConfigManager({ onConfigChange }: Nip95ConfigManagerProps)
- Note: Endpoints are tried in priority order (lower number = higher priority).
- Only enabled endpoints will be used for uploads.
+ {t('settings.nip95.note.title')} {t('settings.nip95.note.priority')}
- If an endpoint fails, the next enabled endpoint will be tried automatically.
+ {t('settings.nip95.note.fallback')}
diff --git a/lib/articlePublisherHelpersPresentation.ts b/lib/articlePublisherHelpersPresentation.ts
index 39314ab..655dfbb 100644
--- a/lib/articlePublisherHelpersPresentation.ts
+++ b/lib/articlePublisherHelpersPresentation.ts
@@ -4,7 +4,7 @@ import type { AuthorPresentationDraft } from './articlePublisher'
import type { SimplePoolWithSub } from '@/types/nostr-tools-extended'
import { buildTags, extractTagsFromEvent, buildTagFilter } from './nostrTagSystem'
import { getPrimaryRelaySync } from './config'
-import { PLATFORM_SERVICE } from './platformConfig'
+import { PLATFORM_SERVICE, MIN_EVENT_DATE } from './platformConfig'
import { generateAuthorHashId } from './hashIdGenerator'
import { generateObjectUrl } from './urlGenerator'
import { getLatestVersion } from './versionManager'
@@ -104,6 +104,7 @@ export function parsePresentationEvent(event: Event): import('@/types/nostr').Au
// Try to extract profile JSON from tag first (new format)
let profileData: {
+ authorName?: string
presentation?: string
contentDescription?: string
mainnetAddress?: string
@@ -191,6 +192,7 @@ export async function fetchAuthorPresentationFromPool(
authorPubkey: pubkey,
service: PLATFORM_SERVICE,
}),
+ since: MIN_EVENT_DATE,
limit: 100, // Get all versions to find the latest
},
]
diff --git a/lib/articleQueries.ts b/lib/articleQueries.ts
index 1fb8ad7..995352e 100644
--- a/lib/articleQueries.ts
+++ b/lib/articleQueries.ts
@@ -6,7 +6,7 @@ import type { Article } from '@/types/nostr'
import { parseArticleFromEvent } from './nostrEventParsing'
import { buildTagFilter } from './nostrTagSystem'
import { getPrimaryRelaySync } from './config'
-import { PLATFORM_SERVICE } from './platformConfig'
+import { PLATFORM_SERVICE, MIN_EVENT_DATE } from './platformConfig'
function createSeriesSubscription(pool: SimplePool, seriesId: string, limit: number) {
const filters = [
@@ -16,6 +16,7 @@ function createSeriesSubscription(pool: SimplePool, seriesId: string, limit: num
seriesId,
service: PLATFORM_SERVICE,
}),
+ since: MIN_EVENT_DATE,
limit,
},
]
diff --git a/lib/nostr.ts b/lib/nostr.ts
index f734873..8a66644 100644
--- a/lib/nostr.ts
+++ b/lib/nostr.ts
@@ -13,7 +13,7 @@ import { checkZapReceipt as checkZapReceiptHelper } from './nostrZapVerification
import { subscribeWithTimeout } from './nostrSubscription'
import { getPrimaryRelay, getPrimaryRelaySync } from './config'
import { buildTagFilter } from './nostrTagSystem'
-import { PLATFORM_SERVICE } from './platformConfig'
+import { PLATFORM_SERVICE, MIN_EVENT_DATE } from './platformConfig'
class NostrService {
private pool: SimplePool | null = null
@@ -89,12 +89,14 @@ class NostrService {
// Subscribe to both 'publication' and 'author' type events
// Authors are identified by tag type='author' in the tag system
// Filter by service='zapwall.fr' to only get notes from this platform
+ // Limit to events published on or after January 6, 2026
const filters = [
{
...buildTagFilter({
type: 'publication',
service: PLATFORM_SERVICE,
}),
+ since: MIN_EVENT_DATE,
limit,
},
{
@@ -102,6 +104,7 @@ class NostrService {
type: 'author',
service: PLATFORM_SERVICE,
}),
+ since: MIN_EVENT_DATE,
limit,
},
]
diff --git a/lib/platformConfig.ts b/lib/platformConfig.ts
index 1067c1c..eff0e9b 100644
--- a/lib/platformConfig.ts
+++ b/lib/platformConfig.ts
@@ -1,3 +1,7 @@
export const PLATFORM_NPUB = 'npub18s03s39fa80ce2n3cmm0zme3jqehc82h6ld9sxq03uejqm3d05gsae0fuu'
export const PLATFORM_BITCOIN_ADDRESS = 'bc1qerauk5yhqytl6z93ckvwkylup8s0256uenzg9y'
export const PLATFORM_SERVICE = 'zapwall.fr'
+
+// Minimum date for Nostr events: January 6, 2026 00:00:00 UTC
+// Timestamp Unix: 1736115200
+export const MIN_EVENT_DATE = 1736115200
diff --git a/lib/reviews.ts b/lib/reviews.ts
index df64e0a..7354017 100644
--- a/lib/reviews.ts
+++ b/lib/reviews.ts
@@ -4,7 +4,7 @@ import type { Review } from '@/types/nostr'
import { parseReviewFromEvent } from './nostrEventParsing'
import { buildTagFilter } from './nostrTagSystem'
import { getPrimaryRelaySync } from './config'
-import { PLATFORM_SERVICE } from './platformConfig'
+import { PLATFORM_SERVICE, MIN_EVENT_DATE } from './platformConfig'
function buildReviewFilters(articleId: string) {
const tagFilter = buildTagFilter({
@@ -17,8 +17,10 @@ function buildReviewFilters(articleId: string) {
kinds: number[]
'#quote'?: string[]
'#article'?: string[]
+ since?: number
} = {
kinds: Array.isArray(tagFilter.kinds) ? tagFilter.kinds as number[] : [1],
+ since: MIN_EVENT_DATE,
}
if (tagFilter['#quote']) {
filterObj['#quote'] = tagFilter['#quote'] as string[]
diff --git a/lib/seriesQueries.ts b/lib/seriesQueries.ts
index ebf9e53..a7038b4 100644
--- a/lib/seriesQueries.ts
+++ b/lib/seriesQueries.ts
@@ -4,7 +4,7 @@ import type { Series } from '@/types/nostr'
import { parseSeriesFromEvent } from './nostrEventParsing'
import { buildTagFilter } from './nostrTagSystem'
import { getPrimaryRelaySync } from './config'
-import { PLATFORM_SERVICE } from './platformConfig'
+import { PLATFORM_SERVICE, MIN_EVENT_DATE } from './platformConfig'
function buildSeriesFilters(authorPubkey: string) {
const tagFilter = buildTagFilter({
@@ -18,6 +18,7 @@ function buildSeriesFilters(authorPubkey: string) {
kinds: tagFilter.kinds as number[],
...(tagFilter.authors ? { authors: tagFilter.authors as string[] } : {}),
...(tagFilter['#series'] ? { '#series': tagFilter['#series'] as string[] } : {}),
+ since: MIN_EVENT_DATE,
},
]
}
@@ -66,6 +67,7 @@ function buildSeriesByIdFilters(seriesId: string) {
type: 'series',
service: PLATFORM_SERVICE,
}),
+ since: MIN_EVENT_DATE,
},
]
}
diff --git a/lib/sponsoring.ts b/lib/sponsoring.ts
index cbaf890..0817c64 100644
--- a/lib/sponsoring.ts
+++ b/lib/sponsoring.ts
@@ -2,7 +2,7 @@ import { nostrService } from './nostr'
import type { Article } from '@/types/nostr'
import { getPrimaryRelaySync } from './config'
import { buildTagFilter, extractTagsFromEvent } from './nostrTagSystem'
-import { PLATFORM_SERVICE } from './platformConfig'
+import { PLATFORM_SERVICE, MIN_EVENT_DATE } from './platformConfig'
function subscribeToPresentation(pool: import('nostr-tools').SimplePool, pubkey: string): Promise {
const filters = [
@@ -12,6 +12,7 @@ function subscribeToPresentation(pool: import('nostr-tools').SimplePool, pubkey:
authorPubkey: pubkey,
service: PLATFORM_SERVICE,
}),
+ since: MIN_EVENT_DATE,
limit: 1,
},
]
diff --git a/locales/en.txt b/locales/en.txt
index c83f62b..3dc3fd5 100644
--- a/locales/en.txt
+++ b/locales/en.txt
@@ -192,3 +192,8 @@ settings.nip95.list.cancel=Cancel
settings.nip95.list.remove=Remove
settings.nip95.remove.confirm=Are you sure you want to remove this endpoint?
settings.nip95.empty=No endpoints configured
+settings.nip95.list.priorityLabel=Priority: {{priority}} | ID: {{id}}
+settings.nip95.list.editUrl=Click to edit URL
+settings.nip95.note.title=Note:
+settings.nip95.note.priority=Endpoints are tried in priority order (lower number = higher priority). Only enabled endpoints will be used for uploads.
+settings.nip95.note.fallback=If an endpoint fails, the next enabled endpoint will be tried automatically.
diff --git a/locales/fr.txt b/locales/fr.txt
index 396ae70..cca3f1f 100644
--- a/locales/fr.txt
+++ b/locales/fr.txt
@@ -192,3 +192,8 @@ settings.nip95.list.cancel=Annuler
settings.nip95.list.remove=Supprimer
settings.nip95.remove.confirm=Êtes-vous sûr de vouloir supprimer cet endpoint ?
settings.nip95.empty=Aucun endpoint configuré
+settings.nip95.list.priorityLabel=Priorité: {{priority}} | ID: {{id}}
+settings.nip95.list.editUrl=Cliquer pour modifier l'URL
+settings.nip95.note.title=Note :
+settings.nip95.note.priority=Les endpoints sont essayés dans l'ordre de priorité (nombre plus bas = priorité plus haute). Seuls les endpoints activés seront utilisés pour les uploads.
+settings.nip95.note.fallback=Si un endpoint échoue, le prochain endpoint activé sera essayé automatiquement.
diff --git a/public/locales/en.txt b/public/locales/en.txt
index 04d1a72..a1e7149 100644
--- a/public/locales/en.txt
+++ b/public/locales/en.txt
@@ -18,6 +18,17 @@ nav.publish=Publish profile
nav.createAuthorPage=Create author page
nav.loading=Loading...
+# Documentation
+docs.title=Documentation
+docs.userGuide=User Guide
+docs.faq=FAQ
+docs.publishing=Publishing Guide
+docs.payment=Payment Guide
+docs.error=Error
+docs.error.loadFailed=Unable to load documentation.
+docs.meta.description=Complete documentation for zapwall.fr
+docs.loading=Loading documentation...
+
# Categories
category.science-fiction=Science Fiction
category.scientific-research=Scientific Research
@@ -182,3 +193,8 @@ settings.nip95.list.cancel=Cancel
settings.nip95.list.remove=Remove
settings.nip95.remove.confirm=Are you sure you want to remove this endpoint?
settings.nip95.empty=No endpoints configured
+settings.nip95.list.priorityLabel=Priority: {{priority}} | ID: {{id}}
+settings.nip95.list.editUrl=Click to edit URL
+settings.nip95.note.title=Note:
+settings.nip95.note.priority=Endpoints are tried in priority order (lower number = higher priority). Only enabled endpoints will be used for uploads.
+settings.nip95.note.fallback=If an endpoint fails, the next enabled endpoint will be tried automatically.
diff --git a/public/locales/fr.txt b/public/locales/fr.txt
index fe44680..f517e8f 100644
--- a/public/locales/fr.txt
+++ b/public/locales/fr.txt
@@ -18,6 +18,17 @@ nav.publish=Publier le profil
nav.createAuthorPage=Créer page auteur
nav.loading=Chargement...
+# Documentation
+docs.title=Documentation
+docs.userGuide=Guide d'utilisation
+docs.faq=FAQ
+docs.publishing=Guide de publication
+docs.payment=Guide de paiement
+docs.error=Erreur
+docs.error.loadFailed=Impossible de charger la documentation.
+docs.meta.description=Documentation complète pour zapwall.fr
+docs.loading=Chargement de la documentation...
+
# Categories
category.science-fiction=Science-fiction
category.scientific-research=Recherche scientifique
@@ -182,3 +193,8 @@ settings.nip95.list.cancel=Annuler
settings.nip95.list.remove=Supprimer
settings.nip95.remove.confirm=Êtes-vous sûr de vouloir supprimer cet endpoint ?
settings.nip95.empty=Aucun endpoint configuré
+settings.nip95.list.priorityLabel=Priorité: {{priority}} | ID: {{id}}
+settings.nip95.list.editUrl=Cliquer pour modifier l'URL
+settings.nip95.note.title=Note :
+settings.nip95.note.priority=Les endpoints sont essayés dans l'ordre de priorité (nombre plus bas = priorité plus haute). Seuls les endpoints activés seront utilisés pour les uploads.
+settings.nip95.note.fallback=Si un endpoint échoue, le prochain endpoint activé sera essayé automatiquement.