Source code for my personal website.
Production:
- Website: https://yuricunha.com
Please use your own AI/mascot name, model and provider credentials when adapting this project.
- Project overview
- Features
- Repository layout
- Tech stack
- Local development
- Environment variables
- Localization and translation
- SEO and indexing
- Scripts
- Validation
- Deployment
- Contributing
- License
- Credits
- Contact
This is the source code for my personal website, docs app and shared package workspace.
The repository is organized as a monorepo (Turbo + pnpm) so that the main app and internal packages can evolve together.
- Localized portfolio, blog, projects, snippets, about, music, contact and sitemap pages.
- Authenticated admin surfaces for content and operational workflows.
- Cursor-inspired warm visual system shared between the website and docs app.
- MDX content collections for blog posts, project pages, snippets and docs.
- SEO surfaces for search engines and LLM crawlers:
sitemap.xml,robots.txt,rss.xml, locale RSS feeds andllms.txt. - Dev-only OpenAI-compatible translation generator for adding new locales locally.
- Shared UI package with Tailwind v4 preset, typography, code styling and reusable primitives.
apps/
web/ main website
docs/ documentation site
packages/
db/ database access (Drizzle)
env/ env validation
emails/ email templates
i18n/ internationalization
ui/ shared UI components
utils/ shared utilities
...
- Runtime: Node.js (see
.nvmrc) - Package manager: pnpm (see
packageManagerinpackage.json) - Monorepo: Turborepo
- Web: Next.js App Router, React, TypeScript
- API: tRPC
- Database: PostgreSQL, Drizzle ORM
- Email: React Email, Resend
- i18n: next-intl (localized routes under
apps/web/src/app/[locale]) - Content: content-collections + MDX
- Styling: Tailwind CSS v4 + shared Cursor-inspired UI preset
- Testing: Vitest (unit), Playwright (e2e)
- Node.js (aligned with
.nvmrc) - pnpm
- PostgreSQL (or a compatible managed provider)
-
Install dependencies
pnpm install
-
Create your local env file
cp .env.example .env.local
-
Initialize the database (optional, if you need DB features locally)
pnpm db:push
-
Start the dev servers
pnpm dev
This repository is actively maintained and dependencies across all apps and packages are updated regularly.
Recommended upgrade workflow:
pnpm -r up --latest
pnpm install
pnpm build:mdx
pnpm check
pnpm test:unit
pnpm check:knip
pnpm --filter @isyuricunha/web build
pnpm --filter @isyuricunha/docs buildIf upgrades introduce runtime issues, prefer debugging in development mode (pnpm dev:web) to get non-minified React errors.
Core tooling:
- Node.js:
>=22(seepackage.json#engines.node) - pnpm:
10.33.2(seepackage.json#packageManager) - TypeScript:
^6.0.3 - Turbo:
^2.9.14 - Vitest:
^4.1.7 - ESLint:
^10.4.0 - Prettier:
^3.8.3
Web apps:
- Next.js:
16.2.6 - React:
19.2.6 - Zod:
4.4.3 - tRPC:
11.17.0 - TanStack React Query:
^5.100.14 - TailwindCSS:
^4.3.0
To list all installed versions in the workspace:
pnpm -r list --depth 0Environment variables are documented in .env.example.
The canonical schema is defined in packages/env/src/index.ts.
For production URLs (used in emails, canonical links, etc.), set:
NEXT_PUBLIC_WEBSITE_URL="https://yuricunha.com"Supported locales are defined in packages/i18n/src/config.ts. Message files live in packages/i18n/src/messages.
The local translation generator can create a new locale from an OpenAI-compatible endpoint. It is designed for developer machines and refuses production/Vercel environments.
Required local variables:
OPENAI_COMPATIBLE_BASE_URL="https://provider.example/v1"
OPENAI_COMPATIBLE_API_KEY="..."
OPENAI_COMPATIBLE_MODEL="model-name"Plan a translation without writing files:
pnpm translate:site -- --target es --dry-runUse smaller batches for slower or timeout-prone models:
pnpm translate:site -- --target es --batch-size small
pnpm translate:site -- --target es --batch-size medium
pnpm translate:site -- --target es --batch-size largejp resolves to ja; cn and zh resolve to zh-CN.
The site exposes:
/sitemap.xml
/robots.txt
/rss.xml
/llms.txt
/<locale>/rss.xml
Admin, API and password-reset surfaces are marked as non-indexable. Public content pages provide canonical metadata, locale alternates, Open Graph/Twitter data and structured data where applicable.
Common tasks:
pnpm dev
pnpm dev:web
pnpm dev:docs
pnpm build
pnpm build:mdx
pnpm lint
pnpm type-check
pnpm test:unit
pnpm test:e2e
pnpm format:check
pnpm check:knip
pnpm translate:site -- --target es --dry-runDatabase tasks:
pnpm db:check
pnpm db:generate
pnpm db:migrate
pnpm db:push
pnpm db:seed
pnpm db:studioRun this sequence before committing:
pnpm build:mdx
pnpm check
pnpm test:unitFor full verification:
pnpm check:knip
pnpm --filter @isyuricunha/web build
pnpm --filter @isyuricunha/docs buildThe project is designed to be deployed on Vercel.
Notes:
- Ensure all required environment variables are set.
- The monorepo uses Turbo pipelines; the default root
pnpm buildis the expected build command.
Common browser console messages:
Failed to load resource: net::ERR_BLOCKED_BY_CLIENTtypically indicates a browser extension (ad blocker/privacy tooling) is blocking a request.- Minified React errors in production builds are best debugged by reproducing the issue in development mode.
This is primarily a personal project.
If you want to contribute:
- Open an issue describing the change.
- Keep changes small and focused.
- Prefer tests for non-trivial logic.
See license.md.
This project began as an adaptation inspired by Nelson Lai's website and has evolved significantly since then.
Thank you to Nelson for the original inspiration.
- Email: me@yuricunha.com
- GitHub: https://github.com/isyuricunha
- Website: https://yuricunha.com