A professional portfolio and service website built with Next.js, showcasing tech coaching, professional development, and local craft services.
This website serves as a platform for:
- Tech coaching and consultation services
- Professional development and career coaching
- Local craft and print services (Central Virginia)
- Industry insights and strategic guidance
- Technical blog and resources
- Framework: Next.js 14.1.0 with React Server Components
- Styling: Tailwind CSS 3.4.1 with Typography plugin
- Content: MDX with next-mdx-remote (RSC-compatible)
- Analytics: Hotjar
- Testing: Jest with React Testing Library
- Type Checking: TypeScript
- Linting: ESLint with TypeScript support
- Build Tools: PostCSS, Sharp for image optimization
- Environment: dotenv for environment variables
.
├── src/
│ ├── app/ # Next.js app directory (RSC)
│ ├── components/ # Shared React components
│ ├── lib/ # Utility functions
│ ├── content/ # MDX content
│ ├── __tests__/ # Test files
│ └── docs/ # Documentation
├── public/ # Static assets
├── content/ # Root content directory
├── .github/ # GitHub workflows
├── .next/ # Next.js build output
├── node_modules/ # Dependencies
├── next.config.js # Next.js configuration
├── tailwind.config.ts # Tailwind CSS configuration
├── postcss.config.js # PostCSS configuration
├── jest.config.js # Jest configuration
├── tsconfig.json # TypeScript configuration
└── package.json # Project dependencies
The project uses two different approaches for content management:
Used for content that is primarily text-based and requires minimal interactivity:
- Home page sections
- Legal documents (Terms of Service, Privacy Policy)
- Blog posts
These pages use the getMDXContent
utility to parse and render MDX files stored in the content/
directory. The MDX content is processed using next-mdx-remote
with React Server Components (RSC) support.
Example MDX structure:
---
title: "Terms of Service"
lastUpdated: "2024-03-13"
summary: "Legal terms for using Pythoness Programmer services"
---
Content here...
Used for features requiring complex interactivity and state management:
- Vibe Coding Cheatsheet - A professional showcase of TailwindCSS capabilities combined with interactive features
The cheatsheet is implemented as a React component-based page with:
- Custom components for specific functionality
- Advanced TailwindCSS styling techniques and patterns
- Structured data in TypeScript files
- Interactive features like copy-to-clipboard
- Dynamic state management
- Custom styling and animations
- Responsive design patterns and best practices
This approach allows for more complex user interactions and immediate feedback that wouldn't be practical with static MDX content, while serving as a living example of professional TailwindCSS implementation.
- Responsive design with mobile-first approach
- Gradient backgrounds with animated patterns
- Accessible UI components
- Integrated booking system
- Newsletter subscription
- Service cards with hover effects
- Professional experience showcase
- Local craft services section
- MDX-based blog system with RSC support
- Vibe Coding Cheatsheet - Professional TailwindCSS showcase & developer resource (Freebie)
- Sourdough Corner - Local craft baking resource and guide (Freebie)
- Enhanced error handling with user feedback
- Input validation and sanitization for security
- Comprehensive testing suite
The blog is implemented using MDX for content management with React Server Components. Here's how to work with it:
- Create new blog posts:
# Create a new blog post
touch src/content/blog/posts/your-post-title.mdx
- Blog post frontmatter structure:
---
title: "Your Post Title"
date: "2024-03-13"
description: "A brief description of your post"
author: "Your Name"
tags: ["tag1", "tag2"]
image: "url hosting image"
---
Your content here...
- Available MDX components:
// Example usage in MDX files
<Callout type="info">
This is an info callout
</Callout>
<CodeBlock language="typescript">
const example = "code here";
</CodeBlock>
- RSS Feed:
The blog includes an RSS feed for subscribers to stay updated with new posts. The feed is available at /feed.xml
and includes:
- Full post content
- Publication dates
- Author information
- Tags as categories
- Automatic updates when new posts are published
The feed is cached for an hour to maintain good performance and can be accessed through the RSS link in the blog header or on the main blog page.
The application includes several security measures:
- Input Validation: All user inputs are validated before processing
- Content Sanitization: File paths and content are sanitized to prevent injection attacks
- Error Boundaries: Robust error handling to prevent exposing sensitive information
- Filepath Validation: Protection against directory traversal attacks
Functions for handling MDX content with proper error handling and security:
// Get content from an MDX file with validation
const { source, frontmatter } = await getMDXContent('path/to/file.mdx');
// Get all blog posts sorted by date
const posts = await getAllPosts();
// Get a specific blog post by its slug
const post = await getPostBySlug('post-slug');
Functions for validating and sanitizing inputs:
// Validate string input
const isValid = isValidString(userInput);
// Sanitize user input
const safeInput = sanitizeString(userInput);
// Validate email format
const isValidEmail = isValidEmail(emailInput);
// Validate schema with multiple fields
const validation = validateData(formData, schema);
if (!validation.valid) {
// Handle validation errors
console.error(validation.errors);
}
Functions for standardized error handling:
// Log errors with context
logError('Failed to process data', error, { userId, action });
// Safely execute code with error handling
const result = await tryCatch(
async () => await fetchData(),
'Failed to fetch data',
{ id: 123 }
);
- Deep forest green: #2E3D2A (
--brand-green-dark
) - Rich purple: #442B48 (
--brand-purple-dark
) - Vibrant green accent: #32d24d (
--brand-green-accent
) - Soft cream: #F4f1de (
--brand-cream
) - Light purple accent: #D8B9F7 (
--brand-purple-light
) - Bright Blue: #00A6FB (
--brand-blue
)
- White: #FFFFFF (
--white
) - White with opacity:
- 10% opacity: rgba(255, 255, 255, 0.1) (
--white-opacity-10
) - 20% opacity: rgba(255, 255, 255, 0.2) (
--white-opacity-20
) - 90% opacity: rgba(255, 255, 255, 0.9) (
--white-opacity-90
)
- 10% opacity: rgba(255, 255, 255, 0.1) (
Common color applications:
- Text on dark:
text-white
,text-white/90
,text-brand-cream
- Text on light:
text-brand-purple-dark
,text-brand-green-dark
- Accents:
text-brand-green-accent
,text-brand-purple-light
,text-brand-blue
- Backgrounds: Dark gradient combinations of
brand-green-dark
andbrand-purple-dark
- Overlays:
bg-white/5
,bg-white/10
withbackdrop-blur-sm
/* Brand Colors */
--brand-green-dark: #2E3D2A; /* Deep forest green */
--brand-purple-dark: #442B48; /* Rich purple */
--brand-green-accent: #32d24d; /* Vibrant green accent */
--brand-cream: #F4f1de; /* Soft cream */
--brand-purple-light: #D8B9F7; /* Light purple accent */
--brand-blue: #00A6FB; /* Bright Blue */
/* UI Colors */
--white: #FFFFFF; /* Pure white for contrast */
--white-opacity-10: rgba(255, 255, 255, 0.1);
--white-opacity-20: rgba(255, 255, 255, 0.2);
--white-opacity-90: rgba(255, 255, 255, 0.9);
To run the project locally:
# Install dependencies
npm install
# Run development server
npm run dev
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Build for production
npm run build
# Start production server
npm start
# Run linting
npm run lint
The project uses Jest and React Testing Library for testing:
# Run all tests
npm test
# Run tests in watch mode
npm run test:watch
# Run tests with coverage report
npm test -- --coverage
Test files follow this naming convention:
__tests__/lib/*.test.ts
- for utility function tests__tests__/components/*.test.tsx
- for React component tests
A GitHub Actions workflow runs on all PRs and pushes to the main branch:
- Runs linting checks
- Executes all tests
- Performs a security audit
- Builds the application
The project uses the following environment variables:
NEXT_PUBLIC_HOTJAR_ID
- Hotjar tracking ID- Additional environment variables can be added in
.env.local
- Hero - Introduction and primary CTAs
- Process - How tech coaching works
- Services - Digital services overview
- Experience - Professional background
- Contact - Booking options and rates
- Newsletter - Industry insights signup
- Blog - Technical articles and resources
- Vibe Coding Cheatsheet - Professional TailwindCSS showcase & developer resource (Freebie)
- Sourdough Corner - Local craft baking resource and guide (Freebie)
The project follows a consistent set of coding standards documented in src/docs/naming-conventions.md
, including:
- Naming conventions for variables, functions, and components
- File organization principles
- Documentation requirements
- TypeScript best practices
The site is built for deployment on Vercel or similar platforms that support Next.js.
For questions or collaborations: admin@pythonessprogrammer.com
This project is licensed under the MIT License - see the LICENSE file for details.