Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FOOTBALL_API_KEY=
50 changes: 50 additions & 0 deletions .github/workflows/node-ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: NodeJS CI

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

on:
push:
branches: [main, dev]
pull_request:
types: [opened, synchronize]
workflow_dispatch: {}

jobs:
lint:
name: Lint, format and Astro Check (ESLint + Prettier + Astro)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install pnpm (action)
uses: pnpm/action-setup@v4
with:
version: 10

- name: Setup Node.js (with pnpm cache)
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'

- name: Restore node_modules cache
id: node-modules-cache
uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
node-modules-${{ runner.os }}-pnpm-

- name: Install dependencies (pnpm) if cache miss
if: steps.node-modules-cache.outputs.cache-hit != 'true'
run: pnpm install --frozen-lockfile

- name: Run ESLint (ESLint + Prettier)
run: pnpm exec eslint . --ext .js,.jsx,.ts,.tsx,.astro --max-warnings=0

- name: Run Astro Check
run: pnpm astro check
5 changes: 5 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
dist
.build
.astro
pnpm-lock.yaml
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
> **¡Hola! Soy Theyobii.** Este es el repositorio de mi portafolio web personal, construido para mostrar mis habilidades y proyectos de desarrollo frontend. El sitio está diseñado para ser ultrarrápido y SEO-friendly, aprovechando la arquitectura de "islas" de Astro.

### 🖼️ Previsualización del Sitio
<img width="1090" height="292" alt="image" src="https://github.com/user-attachments/assets/dc5c7ddc-4ec8-45eb-b7eb-083750e98229" />

<img width="1090" height="292" alt="image" src="https://github.com/user-attachments/assets/dc5c7ddc-4ec8-45eb-b7eb-083750e98229" />

### 🌐 Demo en Vivo

Expand All @@ -23,9 +23,10 @@ https://mini-portfolio-sigma-33.vercel.app/

Este proyecto combina lo mejor del desarrollo web moderno para un rendimiento excepcional:

* **Astro:** Como *framework* principal, para el *Server-Side Rendering* (SSR) y la generación de sitios estáticos, asegurando cero JavaScript por defecto y una velocidad de carga máxima.
* **React:** Se utiliza en componentes específicos ("Astro Islands") donde se requiere interactividad, estado o lógica compleja (ej. el formulario de contacto).
* **Tailwind CSS v3:** Para un diseño rápido, *utility-first* y completamente *responsive*.
- **Astro:** Como _framework_ principal, para el _Server-Side Rendering_ (SSR) y la generación de sitios estáticos, asegurando cero JavaScript por defecto y una velocidad de carga máxima.
- **React:** Se utiliza en componentes específicos ("Astro Islands") donde se requiere interactividad, estado o lógica compleja (ej. el formulario de contacto).
- **Tailwind CSS v3:** Para un diseño rápido, _utility-first_ y completamente _responsive_.

---

## ⚙️ Configuración y Desarrollo Local
Expand All @@ -36,12 +37,13 @@ Sigue estos pasos para obtener una copia del proyecto y ejecutarlo en tu máquin

Asegúrate de tener instalado:

* [Node.js](https://nodejs.org/en/) (versión 18+)
* npm (viene con Node.js) o yarn / pnpm.
- [Node.js](https://nodejs.org/en/) (versión 18+)
- npm (viene con Node.js) o yarn / pnpm.

### Instalación

1. **Clonar el Repositorio:**

```bash
git clone [https://github.com/Theyobii/portfolio.git](https://github.com/Theyobii/portfolio.git)
cd portfolio
Expand All @@ -59,5 +61,3 @@ Ejecuta el servidor de desarrollo en modo local. Esto abrirá el sitio en `http:
```bash
npm run dev
```


77 changes: 36 additions & 41 deletions astro.config.mjs
Original file line number Diff line number Diff line change
@@ -1,50 +1,45 @@
// @ts-check
import { defineConfig } from 'astro/config';
import { defineConfig, envField } from 'astro/config'

import react from '@astrojs/react';
import tailwind from "@astrojs/tailwind"
import react from '@astrojs/react'
import tailwind from '@astrojs/tailwind'
import vercel from '@astrojs/vercel'

// For alias imports
import { fileURLToPath, URL } from "node:url"
import { fileURLToPath, URL } from 'node:url'

// https://astro.build/config
export default defineConfig({
integrations: [
react(),
tailwind(),
],
vite: {
plugins: [],
resolve: {
alias: {
"@styles": fileURLToPath(
new URL(
"./src/styles",
import.meta.url
)
),
"@assets": fileURLToPath(
new URL(
"./src/assets",
import.meta.url
)
),
"@components": fileURLToPath(
new URL(
"./src/components",
import.meta.url
)
),
},
},
},
experimental: {
csp: true,
},

adapter: vercel({
experimentalStaticHeaders: true,
}),

integrations: [react(), tailwind()],

output: "static",
build: {
inlineStylesheets: "auto",
vite: {
resolve: {
alias: {
'@styles': fileURLToPath(new URL('./src/styles', import.meta.url)),
'@assets': fileURLToPath(new URL('./src/assets', import.meta.url)),
'@components': fileURLToPath(new URL('./src/components', import.meta.url)),
},
},
server: {
host: true,
port: 4321,
},

output: 'server',

env: {
schema: {
FOOTBALL_API_KEY: envField.string({ context: 'server', access: 'secret' }),
},
});
validateSecrets: false,
},

server: {
host: true,
port: 4321,
},
})
139 changes: 139 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { defineConfig } from 'eslint/config'
import js from '@eslint/js'
import globals from 'globals'

import tsPlugin from '@typescript-eslint/eslint-plugin'
import tsParser from '@typescript-eslint/parser'

import reactPlugin from 'eslint-plugin-react'
import reactHooks from 'eslint-plugin-react-hooks'
import tailwind from 'eslint-plugin-tailwindcss'
import importPlugin from 'eslint-plugin-import'
import prettierPlugin from 'eslint-plugin-prettier'

import astroPlugin from 'eslint-plugin-astro'
import astroParser from 'astro-eslint-parser'

import { FlatCompat } from '@eslint/eslintrc'
import path from 'path'
import url from 'url'

const __dirname = path.dirname(url.fileURLToPath(import.meta.url))
const compat = new FlatCompat({ baseDirectory: __dirname })

export default defineConfig([
{
ignores: ['dist', 'build', 'node_modules', '.cache', './.astro/**', '*.config.*'],
settings: {
react: { version: 'detect' },
},
},

js.configs.recommended,

{
files: ['**/*.{js,jsx,ts,tsx}'],
extends: compat.extends('plugin:react/recommended', 'plugin:@typescript-eslint/recommended', 'prettier'),
plugins: {
react: reactPlugin,
'@typescript-eslint': tsPlugin,
'react-hooks': reactHooks,
tailwindcss: tailwind,
import: importPlugin,
prettier: prettierPlugin,
},
settings: {
'import/resolver': {
typescript: {
project: ['./tsconfig.eslint.json'],
},
},
react: { version: 'detect' },
},
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
ecmaFeatures: { jsx: true },
project: ['./tsconfig.eslint.json'],
},
globals: globals.browser,
},
rules: {
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{
args: 'all',
argsIgnorePattern: '^_',
caughtErrors: 'all',
caughtErrorsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_',
varsIgnorePattern: '^_',
ignoreRestSiblings: true,
},
],
'@typescript-eslint/no-explicit-any': 'warn',
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
'prefer-const': 'error',
'no-var': 'error',
'tailwindcss/classnames-order': 'error',
'tailwindcss/no-custom-classname': 'error',
'tailwindcss/no-contradicting-classname': 'error',
'import/no-unresolved': 'error',
'prettier/prettier': 'error',
'react/prop-types': 'off',
'react/react-in-jsx-scope': 'off',
},
},

{
files: ['**/*.astro'],
extends: compat.extends('prettier'),
processor: 'astro/astro',
plugins: {
astro: astroPlugin,
prettier: prettierPlugin,
import: importPlugin,
'@typescript-eslint': tsPlugin,
'react-hooks': reactHooks,
tailwindcss: tailwind,
},
settings: {
'import/resolver': {
typescript: {
project: ['./tsconfig.eslint.json'],
},
},
react: { version: 'detect' },
},
languageOptions: {
parser: astroParser,
parserOptions: {
parser: tsParser,
ecmaVersion: 2020,
sourceType: 'module',
ecmaFeatures: { jsx: false },
extraFileExtensions: ['.astro'],
},
globals: globals.browser,
},
rules: {
'import/no-unresolved': 'off',
'prettier/prettier': 'error',
'react/react-in-jsx-scope': 'off',
'react/jsx-uses-react': 'off',
'react/jsx-uses-vars': 'off',
'@typescript-eslint/consistent-type-definitions': 'off',
},
},

{
files: ['src/content.config.ts'],
rules: {
'import/no-unresolved': 'off',
},
},
])
34 changes: 30 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,50 @@
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"build": "astro build",
"build": "astro build && node ./scripts/gen_sitemap.ts https://mini-portfolio-sigma-33.vercel.app dist > dist/sitemap.xml",
"preview": "astro preview",
"astro": "astro"
"astro": "astro",
"type-check": "tsc --noEmit",
"lint": "eslint . --ignore-pattern \"./.astro/**\" --ignore-pattern \"./dist/**\"",
"lint:fix": "eslint . --fix --ignore-pattern \"./.astro/**\" --ignore-pattern \"./dist/**\"",
"format": "prettier --write .",
"format:check": "prettier --check ."
},
"dependencies": {
"@astrojs/check": "^0.9.5",
"@astrojs/react": "^4.4.0",
"@fontsource-variable/inter": "^5.2.8",
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.1",
"astro": "^5.14.4",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-icons": "^5.5.0"
"react-icons": "^5.5.0",
"typescript": "^5.9.3"
},
"devDependencies": {
"@astrojs/tailwind": "^6.0.2",
"@astrojs/vercel": "^9.0.2",
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.38.0",
"@typescript-eslint/eslint-plugin": "^8.46.2",
"@typescript-eslint/parser": "^8.46.2",
"astro-eslint-parser": "^1.2.2",
"autoprefixer": "^10.4.21",
"eslint": "^9.38.0",
"eslint-config-prettier": "^10.1.8",
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-astro": "^1.4.0",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-tailwindcss": "^3.18.2",
"globals": "^16.4.0",
"postcss": "^8.5.6",
"prettier": "^3.6.2",
"prettier-plugin-astro": "^0.14.1",
"prettier-plugin-tailwindcss": "^0.6.14",
"tailwindcss": "3.4.17"
}
}
}
Loading