Members
(constant) CONSENT_STORAGE_KEY
Where the visitor's answer is kept. _app reads the same key from its inline
bootstrap so a returning visitor's grant is replayed into Consent Mode before
gtag.js ever runs — otherwise every visit would start denied.
- Source:
(constant) OG_IMAGE_WIDTH
SDD-L04: dimensions and alt added alongside the URL. Without og:image:width/height a scraper
has to fetch the image before it can lay out a card, and some (LinkedIn in particular) fall back to
a small preview or no image rather than wait. Every OG image this site references is 1200x630 —
og-home.jpg and all 15 post images in public/posts/ — so the values are accurate rather than
guessed. og:image:alt is the accessible description consumers read out.
- Source:
(constant) OG_LOCALES
Tag builders for
These are plain functions returning arrays of elements, deliberately NOT React
components. next/head only picks up tags that are direct children, inside a
single React.Fragment, or in an array — a custom component renders server-side
and then vanishes on client-side navigation (vercel/next.js#8384). Arrays are
documented as supported, so this split is safe where a
- Source:
(constant) STATUS_ICONS
SDD-L12-T8. One icon per status item, keyed by testId so a rename in site.ts fails loudly
here rather than silently rendering nothing. Kept in the component because site.ts is data —
importing React components into it would make every consumer of the constants pull in icons.
- Source:
(constant) UNTRANSLATED_PATH_PREFIXES
Paths whose content is identical in every locale, so no es/gl alternate may be claimed.
SDD-L08. data/legal/ holds three files with no locale suffix and legal/[slug].tsx never
receives the locale, so the same English document is served at /legal/*, /es/legal/* and
/gl/legal/* — while these tags told Google three translations existed. hreflang is a
reciprocal claim about translated content; pointing it at the same English text is telling
search engines something untrue, and it invites them to serve a Spanish-speaking reader an
English page they cannot use.
This is a stopgap, not the fix. The fix is L08-T2 — actual es/gl legal documents — which is
owner work: these texts invoke Spanish law (Ley 34/2002, LOPD-GDD, RD 1720/2007) and make
representations to users about data handling. A machine translation is not adequate. Until then,
claiming nothing beats claiming falsely.
- Source:
(constant) alternateLinks
Translated URLs for the current blog post.
- Source:
(constant) articleTags
article:* metadata, emitted for blog posts only.
- Source:
(constant) blogTags
Structured data and hreflang links for a blog post.
- Source:
(constant) consentSignals
The four Consent Mode v2 signals this site can move. Storage that
is not tied to identifying the visitor (functionality_storage,
security_storage) is granted by default in _app and never asked about,
because it is exempt from prior consent.
- Source:
(constant) ogLocaleTags
og:locale alone tells a scraper which language THIS page is; the alternates declare that the other translations exist. hreflang covers this for search engines, but Open Graph consumers (LinkedIn, Facebook, Slack) do not read it.
- Source:
(constant) resolveSeoUrls
Resolve the canonical URL and the derived values every tag group needs.
- Source:
(constant) staticHreflangTags
hreflang links for the static, non-blog pages.
- Source:
ArticlePanel(readTime) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
readTime |
string | The read time of the article |
- Source:
Returns:
- Type
- JSX.Element
Example
<ArticlePanel readTime="2" />;
AsidePanel() → {JSX.Element}
- Source:
Returns:
- Type
- JSX.Element
Example
<AsidePanel />;
Avatar(name, description, img, alt) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
name |
string | Name of the user |
description |
string | Description of the user |
img |
string | Image of the user |
alt |
string | Alt text for the image |
- Source:
Returns:
- Avatar component
- Type
- JSX.Element
Example
<Avatar name="John Doe" description="Lorem ipsum" img="/images/avatar.jpg" alt="John Doe" />;
BackgroundImage() → {JSX.Element}
- Source:
Returns:
- Type
- JSX.Element
Example
<BackgroundImage />;
ControlButtons(disabled, withPadding, onClickClose, onClickMinimise, onClickMaximise) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
disabled |
boolean | If true, the maximise button will be disabled |
withPadding |
boolean | If true, the container will have padding |
onClickClose |
function | Callback function when close button is clicked |
onClickMinimise |
function | Callback function when minimise button is clicked |
onClickMaximise |
function | Callback function when maximise button is clicked |
- Source:
Returns:
- Type
- JSX.Element
Example
<ControlButtons />;
CookieConsent() → {JSX.Element|null}
Prior-consent gate for analytics storage. Until the visitor
answers, _app has already told gtag every identifying signal is denied, so
nothing is written; this component only ever moves that state.
- Source:
Returns:
- Type
- JSX.Element | null
Example
<CookieConsent />;
CountDown(date, caption) → {JSX.Element}
Countdown to date provided in months, days, hours, minutes and seconds
Parameters:
| Name | Type | Description |
|---|---|---|
date |
string | date to countdown to |
caption |
string | caption to display |
- Source:
Returns:
- Type
- JSX.Element
CryptoPrice() → {JSX.Element}
Show the current price of XRP in EUR
- Source:
Returns:
- Type
- JSX.Element
Example
<CryptoPrice />
DateAndHour(children, minutes) → {JSX.Element}
This component is a Clock and a Weather Widget
Parameters:
| Name | Type | Description |
|---|---|---|
children |
ReactNode | The children |
minutes |
number | The number of minutes to update the clock |
- Source:
Returns:
- Type
- JSX.Element
DeploymentStatus() → {JSX.Element}
- Shows the current deployment status
- Source:
Returns:
- DeploymentStatus component
- Type
- JSX.Element
Example
- <DeploymentStatus />
Dialog(dialogRef, open, withPadding, modalMode, header, body, footer, large, label, onClose) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
dialogRef |
React.RefObject.<HTMLDivElement> | Ref to the dialog element |
open |
boolean | If true, the dialog will be open |
withPadding |
boolean | If true, the dialog will have padding |
modalMode |
boolean | If true, the dialog will be not complete screen |
header |
ReactNode | The header of the dialog |
body |
ReactNode | The body of the dialog |
footer |
ReactNode | The footer of the dialog |
large |
boolean | If true, the dialog will be large |
label |
string | Accessible name for the window |
onClose |
function | Invoked when Escape is pressed |
- Source:
Returns:
- Type
- JSX.Element
Example
<Dialog
dialogRef={dialogRef}
open={open}
withPadding={withPadding}
modalMode={modalMode}
header={<h1>Header</h1>}
body={<p>Body</p>}
footer={<button>Footer</button>}
large={large}
/>;
Dock()
This component is the dock that appears on the bottom of the screen
- Source:
Returns:
JSX.Element
FormattedDate(string) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
string |
Date |
- Source:
Returns:
- Type
- JSX.Element
Example
<Date date="01-02-2023" />
GoogleAdsense(client, slot) → {JSX.Element}
- The adsense will be rendered only in production mode and horizontal only on mobile
Parameters:
| Name | Type | Description |
|---|---|---|
client |
string | The client id |
slot |
string | The slot id |
- Source:
Returns:
- Type
- JSX.Element
Example
<GoogleAdsense slot="1234567890" />;
GridLayoutControl(routeName) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
routeName |
string | The name of the route |
- Source:
Returns:
- Type
- JSX.Element
Example
<GridLayoutControl routeName="System Preferences" />;
Header(children) → {JSX.Element}
Header navigation bar component with the following features:
- Bitcoin logo
- Current route
- Social links
- XRP price
- Indexed pages counter
- Total views counter
- Heating temperature
- Date and hour
- Weather Widget
Parameters:
| Name | Type | Description |
|---|---|---|
children |
ReactNode | The children to display: ; |
- Source:
Returns:
- Type
- JSX.Element
Heating() → {JSX.Element}
- Shows the current temperature of the house and the outside temperature
- Source:
Returns:
- News component
- Type
- JSX.Element
Icon(src, alt, testId) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
src |
string | Image source |
alt |
string | Image alt text |
testId |
string | Test id for testing |
- Source:
Returns:
- Type
- JSX.Element
Example
<Icon src="/images/nextjs.svg" alt="NextJS" testId="nextjs-icon" />
IconWithName(icon, alt, name, horizontal, onClick, pressed) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
icon |
string | The path to the icon |
alt |
string | The alt text for the icon |
name |
string | Text to display |
horizontal |
boolean | If true, the icon will be displayed horizontally |
onClick |
function | Makes this a button; omit it for a static tile |
pressed |
boolean | Toggle state, forwarded as aria-pressed |
- Source:
Returns:
- Type
- JSX.Element
Example
<IconWithName icon="/images/icons/terminal.svg" alt="Terminal" name="Terminal" />;
<IconWithName icon="/images/icons/terminal.svg" alt="Terminal" name="Terminal" horizontal />;
IndexedCounter() → {JSX.Element}
This component is used to display the number of indexed pages on Google
- Source:
Returns:
- Type
- JSX.Element
Example
<IndexedCounter />
LangSelect() → {JSX.Element}
- Source:
Returns:
- Type
- JSX.Element
Example
<LangSelect />;
Layout(className, children) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
className |
string | The class name for the different pages |
children |
JSX.Element | Content to be rendered |
- Source:
Returns:
- Type
- JSX.Element
Example
<Layout meta={meta} isBlog={true}>
<div>Content</div>
</Layout>;
NavLinks() → {JSX.Element}
The profile and artifact links, as icons in the left zone beside the identity.
SDD-L12-T9. T8 put them in the right zone, which read as a second cluster of status items hanging off the countdown. They are navigation, not status — on a macOS menu bar that belongs next to the app identity — and that is also where they were before T8 moved them.
- Source:
Returns:
- Type
- JSX.Element
NavList(title, list, category, isCategory) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
title |
string | The title of the list |
list |
Array.<object> | The list of items |
category |
string | The category has other styles |
isCategory |
boolean | If is category the icon will be a folder |
- Source:
Returns:
- Type
- JSX.Element
Example
<NavList title="Categories" list={categories} category={category} isCategory={true} />;
NavigationArrows(hidden, disabledLeft, disabledRight, onClickLeft, onClickRight) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
hidden |
boolean | If true, the arrows will be hidden |
disabledLeft |
boolean | If true, the left arrow will be disabled |
disabledRight |
boolean | If true, the right arrow will be disabled |
onClickLeft |
function | Callback function when left arrow is clicked |
onClickRight |
function | Callback function when right arrow is clicked |
- Source:
Returns:
- Type
- JSX.Element
Example
<NavigationArrows />;
News(string) → {JSX.Element}
- Show the latest news about the city
Parameters:
| Name | Type | Description |
|---|---|---|
string |
city | City name |
- Source:
Returns:
- News component
- Type
- JSX.Element
Notification(title, message, type) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
title |
string | The title of the notification |
message |
string | The message of the notification |
type |
string | The type of the notification |
- Source:
Returns:
- Type
- JSX.Element
Example
<Notification title="Success" message="This is a success message" type="success" />;
<Notification title="Error" message="This is an error message" type="error" />;
PostList(posts, slug, category) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
posts |
Array.<object> | The list of posts |
slug |
string | The slug is used to highlight the selected post |
category |
string | The taxonomy segment being browsed, preserved in every link |
- Source:
Returns:
- Type
- JSX.Element
Example
<PostList posts={posts} slug={slug} category={category} />;
RenderManager(Error, boolean, string, string) → {React.ReactNode}
- Renders children or error/loading icon
SDD-L07: error was typed boolean. It never was one — every caller passes SWR's error, an
Error object, and it typechecked only because useSWR<Data> leaves the error generic at any.
The declaration therefore discarded the only information the widget had about what went wrong,
which is why all ten of them showed the same icon and the same sentence whether the route was
down, the network was gone, or the response no longer matched its contract.
errorTitle still wins when a caller supplies one, so widget-specific wording ("heating
unavailable") is unchanged; the distinction only fills in where there was no wording at all.
Parameters:
| Name | Type | Description |
|---|---|---|
Error |
error | | undefined - the failure, if there was one |
boolean |
loading | loading state |
string |
errorTitle | Title for error icon |
string |
loadingTitle | Title for loading icon |
React.ReactNode |
children | Children to render |
- Source:
Returns:
- Returns children or error/loading icon
- Type
- React.ReactNode
Route() → {JSX.Element}
Translate the route to the current language
- Source:
Returns:
- Type
- JSX.Element
SEO(meta, isBlog, noimage) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
meta |
object | The object containing the meta data for SEO |
isBlog |
boolean | Whether the page is a blog post the SEO changes |
noimage |
boolean | Whether to show the image in the SEO |
- Source:
Returns:
- Type
- JSX.Element
Example
<SEO meta={meta} isBlog={true} />;
SearchInput(value, disabled, onBlur, onChange, placeHolderText, label) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
value |
string | The value of the input |
disabled |
boolean | If true, the input will be disabled |
onBlur |
function | Callback function when input is blurred |
onChange |
function | Callback function when input is changed |
placeHolderText |
string | The placeholder text for the input |
label |
string | Accessible name for the field |
- Source:
Returns:
- Type
- JSX.Element
Example
<SearchInput />;
SidesShift(handleClick, leftPosition, label, expanded) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
handleClick |
function | Makes this a real button; omit it for a decorative grabber |
leftPosition |
boolean | If true, the button will be positioned on the left |
label |
string | Accessible name, required alongside handleClick |
expanded |
boolean | Panel open state, forwarded as aria-expanded |
- Source:
Returns:
- Type
- JSX.Element
Example
<SidesShift />;
<SidesShift handleClick={toggle} label="Show posts" expanded={open} />;
StarCounter() → {JSX.Element}
Component that shows the number of stars of the repository
- Source:
Returns:
Component
- Type
- JSX.Element
TimeRead(readTime) → {JSX.Element}
Parameters:
| Name | Type | Description |
|---|---|---|
readTime |
string | The read time of the article |
- Source:
Returns:
- Type
- JSX.Element
Example
<TimeRead readTime="2" />;
ViewCounter(all) → {JSX.Element}
Component that shows the number of views of the current page or the totally of website, include de new users
Parameters:
| Name | Type | Description |
|---|---|---|
all |
If true, shows the total of views and new users |
- Source:
Returns:
- Type
- JSX.Element
VisibilityManager(hideOnDesktop, hideOnTablet, hideOnMobile) → {ReactElement|null}
Parameters:
| Name | Type | Description |
|---|---|---|
hideOnDesktop |
boolean | If true, the component will be hidden on desktop |
hideOnTablet |
boolean | If true, the component will be hidden on tablet |
hideOnMobile |
boolean | If true, the component will be hidden on mobile |
- Source:
Returns:
- Type
- ReactElement | null
Example
<VisibilityManager hideOnDesktop={true}>
Weather(cities, open, handleClose) → {JSX.Element}
- Show the weather of array of cities and the last news of each city
Parameters:
| Name | Type | Description |
|---|---|---|
cities |
Array.<string> | Cities to get weather |
open |
boolean | Open or close the component |
handleClose |
function | Function to close the component |
- Source:
Returns:
- News component
- Type
- JSX.Element
calculateTimeLeft(date, setTime, timeLeft) → {TimeLeft}
This function is used to calculate the time left until the date
Parameters:
| Name | Type | Description |
|---|---|---|
date |
string | The date to calculate the time left |
setTime |
function | The function to set the time left |
timeLeft |
TimeLeft | The time left object |
- Source:
Returns:
- The time left object
- Type
- TimeLeft
Example
calculateTimeLeft('2021-12-31', setTime)
errorMessageId()
- Decide which of the failure message ids fits this error.
Kept outside the component so the mapping can be read on its own: a route that answered a status we do not accept is a different event from a route that answered a body we do not recognise, and a reader can act on the difference.
- Source:
useDeploymentStatus() → {Object}
- Fetches the deployment status
- Source:
Returns:
- Type
- Object
Example
- const { data, isLoading, error } = useDeploymentStatus();
usePostComponents(meta) → {object}
MDX component overrides that inject the E-E-A-T byline under the post title.
Every MDX body opens with # Title immediately followed by
Parameters:
| Name | Type | Description |
|---|---|---|
meta |
object | Post frontmatter carrying the author and publication date. |
- Source:
Returns:
The MDX components map to hand to
- Type
- object