Skip to content

Commit

Permalink
SEO optimized tutoring page
Browse files Browse the repository at this point in the history
  • Loading branch information
andrecasal committed May 1, 2024
1 parent 56dac93 commit c53e46c
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 3 deletions.
1 change: 1 addition & 0 deletions app/components/newsletter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const Newsletter = ({ className, title, description, buttonText }: NewsletterPro
action="/newsletter"
className={`col-start-1 row-start-1 ${state === 'initial' ? ' opacity-100' : 'pointer-events-none opacity-0'}`}
{...form.props}
encType="multipart/form-data"
>
<AuthenticityTokenInput />
<HoneypotInputs />
Expand Down
20 changes: 17 additions & 3 deletions app/routes/_marketing+/tutoring.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import satisfactionGuarantee from './images/satisfaction-guarantee.png'
import signatureBlack from './images/signature-black.png'
import signatureWhite from './images/signature-white.png'
import { Link } from '@remix-run/react'
import { type LinksFunction } from '@remix-run/node'
import { type V2_MetaFunction, type LinksFunction } from '@remix-run/node'
import { Container } from '~/ui_components/layout/container.tsx'
import { H1 } from '~/ui_components/typography/h1.tsx'
import { P } from '~/ui_components/typography/p.tsx'
Expand All @@ -25,6 +25,20 @@ export const links: LinksFunction = () => {
return [{ rel: 'canonical', href: 'https://andrecasal.com/tutoring' }]
}

export const meta: V2_MetaFunction = () => {
return [
{ title: 'Private tutor for coding or programming subjects' },
{
name: 'description',
content: "Searching for a tutoring and what results? I've helped 650+ students obliterate their exams! Satisfaction 100% guaranteed!",
},
{
name: 'keywords',
content: 'tutoring, private tutoring, private tutor, tutor, programming tutor, coding tutor, computer science tutor, software engineering tutor, web development tutor',
},
]
}

const Tutoring = () => {
const features = [
{
Expand Down Expand Up @@ -358,9 +372,9 @@ const Tutoring = () => {
<Container className="py-32 sm:py-40">
<div className="lg:flex lg:gap-x-10">
<div className="mx-auto max-w-2xl lg:mx-0 lg:flex-auto">
<H1 size="4xl" className="mt-10">
<H2 size="4xl" className="mt-10">
About André
</H1>
</H2>
<P size="lg" className="mt-6 text-muted-700">
André is a serial entrepreneur with a background in software engineering, working for more than {new Date().getFullYear() - 2006} years, with companies like
Calouste Gulbenkian Foundation, American TV network NBC, and energy drink Monster Energy. He has provided technical direction to countless startups, and
Expand Down
136 changes: 136 additions & 0 deletions app/routes/_pseo+/explicacoes.$subjectslug.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { Button } from '~/components/ui/button.tsx'

Check failure on line 1 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

'Button' is defined but never used
import { Icon } from '~/components/ui/icon.tsx'

Check failure on line 2 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

'Icon' is defined but never used
import BackgroundDiagonal from './components/bg-diagonal.tsx'

Check failure on line 3 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ʦ TypeScript

Cannot find module './components/bg-diagonal.tsx' or its corresponding type declarations.

Check failure on line 3 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

'BackgroundDiagonal' is defined but never used
import BackgroundBlur from './components/bg-blur.tsx'

Check failure on line 4 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ʦ TypeScript

Cannot find module './components/bg-blur.tsx' or its corresponding type declarations.

Check failure on line 4 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

'BackgroundBlur' is defined but never used
import BackgroundSquareLines from './components/bg-square-lines.tsx'

Check failure on line 5 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ʦ TypeScript

Cannot find module './components/bg-square-lines.tsx' or its corresponding type declarations.

Check failure on line 5 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

'BackgroundSquareLines' is defined but never used
import collegeLife from '../_marketing+/images/college-life.jpg'
import andreOnMacBookPro from './images/andre-on-macbook-pro.png'

Check failure on line 7 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

'andreOnMacBookPro' is defined but never used
import goncaloBarreiros from './images/goncalo-barreiros.png'

Check failure on line 8 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

'goncaloBarreiros' is defined but never used
import pauloJorge from './images/paulo-jorge.png'

Check failure on line 9 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

'pauloJorge' is defined but never used
import miguelFerreira from './images/miguel-ferreira.png'

Check failure on line 10 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

'miguelFerreira' is defined but never used
import satisfactionGuarantee from './images/satisfaction-guarantee.png'

Check failure on line 11 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

'satisfactionGuarantee' is defined but never used
import signatureBlack from './images/signature-black.png'
import signatureWhite from './images/signature-white.png'
import { Link, useLoaderData } from '@remix-run/react'
import { type LoaderFunction, json, type LinksFunction, type V2_MetaFunction, type LoaderArgs } from '@remix-run/node'
import { Container } from '~/ui_components/layout/container.tsx'
import { H1 } from '~/ui_components/typography/h1.tsx'
import { P } from '~/ui_components/typography/p.tsx'
import { H2 } from '~/ui_components/typography/h2.tsx'
import { H3 } from '~/ui_components/typography/h3.tsx'
import { Span } from '~/ui_components/typography/span.tsx'
import { H4 } from '~/ui_components/typography/h4.tsx'
import { subjects } from './subject-data.ts'
import { Ul } from '~/ui_components/typography/ul.tsx'

export const meta: V2_MetaFunction = ({ params }) => {
const { subjectslug } = params
const subject = subjects.find(s => s.slug === subjectslug)
const { slug, name, prerequisites, topics, software, exercises, isTutorable } = subject

Check failure on line 29 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ʦ TypeScript

Property 'slug' does not exist on type 'Subject | undefined'.

Check failure on line 29 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ʦ TypeScript

Property 'name' does not exist on type 'Subject | undefined'.

Check failure on line 29 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ʦ TypeScript

Property 'prerequisites' does not exist on type 'Subject | undefined'.

Check failure on line 29 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ʦ TypeScript

Property 'topics' does not exist on type 'Subject | undefined'.

Check failure on line 29 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ʦ TypeScript

Property 'software' does not exist on type 'Subject | undefined'.

Check failure on line 29 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ʦ TypeScript

Property 'exercises' does not exist on type 'Subject | undefined'.

Check failure on line 29 in app/routes/_pseo+/explicacoes.$subjectslug.tsx

View workflow job for this annotation

GitHub Actions / ʦ TypeScript

Property 'isTutorable' does not exist on type 'Subject | undefined'.
return [
{ title: `Explicações de ${name}` },
{
name: 'description',
content: `Procuras explicações de ${name} e queres resultados? Ajudei 650+ alunos a obliterar os exames! Satisfação 100% garantida!`,
},
{
name: 'keywords',
content: `explicações, ${name}, tutoria, universidade, estudantes, notas, exames, sucesso, resultados, garantia, tutor, explicador, mentor, explicação, explicadores, mentores, tutorias`,
},
]
}

export const links: LinksFunction = () => {
return [
{
rel: 'preload',
href: collegeLife,
as: 'image',
},
{
rel: 'canonical',
href: `https://andrecasal.com/explicacoes/programacao`,
},
]
}

export async function loader({ params }: LoaderArgs) {
const { subjectslug } = params
const subject = subjects.find(s => s.slug === subjectslug)!
return json({ subject })
}

const Explicacoes = () => {
const { subject } = useLoaderData<typeof loader>()
const { slug, name, prerequisites, topics, software, exercises, isTutorable } = subject

return (
<>
<Container className="relative">
<div className="lg:grid lg:grid-cols-12 lg:gap-x-20">
<div className="pb-24 pt-10 sm:pb-32 lg:col-span-7 lg:pb-56 lg:pt-48 xl:col-span-6">
<div className="mx-auto max-w-2xl lg:mx-0">
<H1 size="5xl" className="mt-24 sm:mt-10">
Explicações de {name}
</H1>
<P size="lg" className="mt-6 text-muted-600">
Aqui tens tudo o que precisas para ter sucesso em <strong>{name}</strong>!
</P>
</div>
</div>
<div className="relative lg:col-span-5 lg:-mr-8 xl:absolute xl:inset-0 xl:left-1/2 xl:mr-0">
<img
className="aspect-[3/2] w-full rounded-2xl bg-muted-50 object-cover lg:absolute lg:inset-0 lg:aspect-auto lg:h-full"
src={collegeLife}
alt="Explicações de Programação"
/>
</div>
</div>
</Container>
<Container className="py-32">
<div className="max-w-3xl text-muted-700">
<H2 size="3xl" className="mt-2 text-muted-900">
Pré-requisitos de {name}
</H2>
<P>Estas são as coisas que já tens que dominar de forma a estares preparado para {name}:</P>
<Ul>
{prerequisites.map(prerequisite => (
<li key={prerequisite}>{prerequisite}</li>
))}
</Ul>
<H2 size="3xl" className="mt-2 text-muted-900">
Tópicos de {name}
</H2>
<P>Esta é a lista da matéria para {name}:</P>
<Ul>
{topics.map(({ name, children }) => (
<li key={name}>
{name}
{children ? (
<Ul>
{children.map(({ name }) => (
<li key={name}>{name}</li>
))}
</Ul>
) : null}
</li>
))}
</Ul>
<H2 size="3xl" className="mt-2 text-muted-900">
Software útil para {name}
</H2>
<Ul>
{software.map(({ name, link }) => (
<li key={name}>
<a href={link} target="_blank" rel="noreferrer" className="underline">
{name}
</a>
</li>
))}
</Ul>
</div>
</Container>
</>
)
}
export default Explicacoes
74 changes: 74 additions & 0 deletions app/routes/_pseo+/subject-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
type Software = {
name: string
link: string
}

type List = {
name: string
children?: List[]
}

type Subject = {
slug: string
name: string
prerequisites: string[]
topics: List[]
software: Software[]
exercises: string[]
isTutorable: boolean
}

export const subjects: Subject[] = [
{
slug: 'sistemas-digitais',
name: 'Sistemas Digitais',
prerequisites: ['Conhecimento básico de álgebra', 'Aritmética e sistemas numéricos (especialmente binário)', 'Manipulação de números e expressões lógicas'],
topics: [
{ name: 'Álgebra de Boole' },
{ name: 'Portas Lógicas (AND, OR, NOT, NAND, NOR, XOR, XNOR)' },
{ name: 'Expressões Booleanas' },
{ name: 'Tabelas de verdade' },
{ name: 'Mapas de Karnaugh' },
{ name: 'Expressões simplificadas' },
{
name: 'Circuitos Combinatórios',
children: [
{ name: 'Multiplexadores' },
{ name: 'Demultiplexadores' },
{ name: 'Codificadores' },
{ name: 'Descodificadores' },
{ name: 'Somador' },
{ name: 'Somador completo' },
],
},
{
name: 'Circuitos Sequenciais',
children: [
{ name: 'Flip-flops (Latch SR, Latch JK, Flip-flop D, Flip-flop T)' },
{ name: 'Registos' },
{ name: 'Contadores' },
{ name: 'Somador sequencial' },
{ name: 'Subtrator sequencial' },
],
},
{ name: 'Máquinas de Estado Finito (FSMs)' },
{ name: 'Síntese Lógica' },
{ name: 'Projeto de Circuitos Digitais' },
{ name: 'Famílias Lógicas (TTL, CMOS)' },
{ name: 'Temporização de Circuitos' },
{ name: 'Memórias (RAM, ROM, EEPROM, Flash)' },
{ name: 'Interfaces Digitais' },
{ name: 'FPGA (Field-Programmable Gate Array)' },
{ name: 'VHDL/Verilog' },
{ name: 'Application-Specific Integrated Circuits (ASICs)' },
],
software: [
{
name: 'Logisim',
link: 'https://sourceforge.net/projects/circuit/',
},
],
exercises: ['Construção de circuitos combinatórios', 'Construção de circuitos sequenciais', 'Programação de microcontroladores'],
isTutorable: true,
},
]

0 comments on commit c53e46c

Please sign in to comment.