feat: search metadata, structured data and indexing rules
Only the production deployment may be indexed; testing and preview builds answer with noindex and a closed robots file. The homepage now describes the person, the services and the FAQ as structured data, and title, description and the 404 page are written for what people search for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
export type FaqItem = {
|
||||
readonly question: string;
|
||||
readonly answer: string;
|
||||
};
|
||||
|
||||
/** Shown in the questions section and passed to search engines as structured data. */
|
||||
export const FAQ: readonly FaqItem[] = [
|
||||
{
|
||||
question: "I am not technical. Is that a problem?",
|
||||
answer:
|
||||
"No. I explain what I am doing in plain language, and you can ask at any time. You do not need to read code.",
|
||||
},
|
||||
{
|
||||
question: "How long am I committed?",
|
||||
answer:
|
||||
"Project work is billed by effort. Either side can end it with two weeks notice to the end of a month.",
|
||||
},
|
||||
{
|
||||
question: "Who owns what you build?",
|
||||
answer:
|
||||
"You do. Code and design belong to you, and you can hand them to another developer.",
|
||||
},
|
||||
{
|
||||
question: "Can you work with our existing team and code?",
|
||||
answer:
|
||||
"Yes. I worked in agencies and product teams for years, so joining an existing project is familiar to me.",
|
||||
},
|
||||
{
|
||||
question: "How do I reach you?",
|
||||
answer:
|
||||
"By email or video call. I work remotely and am available during European business hours.",
|
||||
},
|
||||
{
|
||||
question: "What do you not do?",
|
||||
answer:
|
||||
"Mobile apps for the app stores, Windows software and running your servers. If your project needs those, I say so in the first call.",
|
||||
},
|
||||
];
|
||||
@@ -16,6 +16,8 @@ export type PathPrice = {
|
||||
|
||||
export type ServicePath = {
|
||||
readonly id: string;
|
||||
/** The service in neutral words, as search engines list it. */
|
||||
readonly service: string;
|
||||
/** How the visitor would say it. */
|
||||
readonly need: string;
|
||||
readonly forWhom: string;
|
||||
@@ -34,6 +36,7 @@ export type ServicePath = {
|
||||
export const SERVICE_PATHS: readonly ServicePath[] = [
|
||||
{
|
||||
id: "developer",
|
||||
service: "Web app and frontend development",
|
||||
need: "We need a developer for our product",
|
||||
forWhom: "Startups, product teams, agencies, Web3 teams",
|
||||
headline: "An experienced developer who joins your project.",
|
||||
@@ -76,6 +79,7 @@ export const SERVICE_PATHS: readonly ServicePath[] = [
|
||||
},
|
||||
{
|
||||
id: "rescue",
|
||||
service: "Code review and stabilisation of web apps",
|
||||
need: "Our app needs to become reliable",
|
||||
forWhom: "Teams whose app was built quickly and is now hard to change",
|
||||
headline: "A week to look at your app and fix what is most urgent.",
|
||||
@@ -115,6 +119,7 @@ export const SERVICE_PATHS: readonly ServicePath[] = [
|
||||
},
|
||||
{
|
||||
id: "automation",
|
||||
service: "Process automation and system integration",
|
||||
need: "We want to automate a process",
|
||||
forWhom:
|
||||
"Companies where people copy data between tools or repeat the same steps",
|
||||
@@ -156,6 +161,7 @@ export const SERVICE_PATHS: readonly ServicePath[] = [
|
||||
},
|
||||
{
|
||||
id: "website",
|
||||
service: "Website design and development",
|
||||
need: "I just need a website",
|
||||
forWhom: "Companies and self-employed people who want it taken care of",
|
||||
headline: "A website, built and looked after for you.",
|
||||
|
||||
@@ -1,13 +1,25 @@
|
||||
import { parseEmailParts, type EmailParts } from "@/src/domain/email";
|
||||
import { indexingFor } from "@/src/domain/indexing";
|
||||
|
||||
export const SITE_NAME = "Marc Mintel";
|
||||
export const SITE_URL = "https://mintel.me";
|
||||
|
||||
/** One wording for the browser title, search results and link previews. */
|
||||
export const SITE_TITLE =
|
||||
"Marc Mintel — Freelance developer for web apps and websites";
|
||||
"Freelance web developer for web apps & websites | Marc Mintel";
|
||||
export const SITE_DESCRIPTION =
|
||||
"Freelance developer with 15 years of experience. I build web apps, interfaces and websites, and automate processes between your systems.";
|
||||
"Freelance web developer with 15 years of experience. I build web apps, interfaces and websites with React, Next.js and TypeScript, and automate processes.";
|
||||
export const SITE_LANGUAGE = "en";
|
||||
export const JOB_TITLE = "Freelance web developer";
|
||||
|
||||
/**
|
||||
* Public profiles of the owner (LinkedIn, GitHub, ...). Search engines use them to
|
||||
* connect this site with the same person elsewhere. Only add profiles the owner confirmed.
|
||||
*/
|
||||
export const PROFILES: readonly string[] = [];
|
||||
|
||||
/** Only the production deployment may appear in search results. Set by the build. */
|
||||
export const INDEXING = indexingFor(process.env.NEXT_PUBLIC_TARGET);
|
||||
|
||||
// The contact address, kept in parts on purpose: the complete address must never
|
||||
// appear as one string in the page source (see src/components/EmailLink.tsx).
|
||||
|
||||
Reference in New Issue
Block a user