Markdown Converter
Agent skill for markdown-converter
**Tech Stack**: Vite + Lit Element + TypeScript + Vaadin Router (client-side SPA)
Sign in to like and favorite skills
Tech Stack: Vite + Lit Element + TypeScript + Vaadin Router (client-side SPA)
This is a personal portfolio/website built as a single-page application (SPA) with:
src/, public dir: public/)src/vaadin-routing.js) - client-side onlycss tagged template literals)Every page/feature is a Lit Element custom element defined in
src/components/:
@customElement('element-name') decoratorimport {css, html, LitElement} from 'lit'@property() decorator for reactive state/bio → <bio-element>)Critical Pattern: Components import two CSS modules for styling:
import langCSS from "../css/langCSS"; import mainCSS from "../css/mainCSS"; // or mainCSS-refined static get styles() { return [langCSS, mainCSS, css`...additional styles...`]; }
Why this matters: The CSS import order determines cascade priority.
langCSS handles i18n, mainCSS provides global design tokens, and inline css adds component-specific styles.
Original Brand Colors (DO NOT CHANGE):
#c7a86d or #876618 (primary accent)#a3b7c0 or #81a3a7 (secondary accent)#398718#00aaffCurrent Design System:
src/css/mainCSS.ts - Original CSS with brand colors/fontssrc/css/mainCSS-refined.ts - NEW merged system combining original brand with modern spacing/componentssrc/css/langCSS.ts - Language-specific stylessrc/components/ui/ - Modern UI component library (gh-button, gh-card, gh-input, etc.)Design Philosophy: Elegant, refined, sophisticated aesthetic. Less "plastic" and harsh - subtle borders (2-4px), smooth transitions (300ms), transparent backgrounds with gold tints.
Entry Point:
src/index.html → loads src/vaadin-routing.js → mounts router on #app div
Routes are defined in
vaadin-routing.js:
const app = document.querySelector('#app'); export const router = new Router(app); router.setRoutes([ { path: '/bio', component: 'bio-element', name: 'bio-element' }, { path: '/portfolio', component: 'portfolio-element', name: 'portfolio-element' }, { path: '/', component: 'bio-element' }, // default landing page { path: '(.*)', component: 'not-found-element' } // 404 - MUST BE LAST ]);
Adding a new route (4-step process):
src/components/my-page.ts with @customElement('my-page-element')vaadin-routing.js: import './components/my-page'(.*) route (order matters!)name property (currently unused but matches convention)Navigation: Use
<a href="/path"> links - Vaadin Router intercepts clicks and renders client-side without page reload.
Route Order Critical: The 404 catch-all
(.*) MUST be last, otherwise all routes after it will be unreachable.
CRITICAL: Due to Windows file permission issues with
package.json, use:
./dev.sh
This script:
node_modules exists, runs npm install if missingnpx vite --hostDO NOT run
npm run dev directly - it may fail with file permission errors on Windows/OneDrive.
OneDrive sync can cause file permission errors. If you encounter read/write failures:
cat or grep via terminal instead of file read toolssemantic_search for code discovery when files are inaccessiblenpm run build # or: npx vite build
Output:
dist/ directory ready for deployment
Firebase Configuration:
firebase.json deploys from dist/ directory
Automated Deployment (GitHub Actions):
master → Automatically builds, tests, and deploys to Firebase Hosting live.github/workflows/test.yml)Manual Deployment:
npm run buildfirebase deploy --only hostingBranch Strategy:
master - Production branch (auto-deploys on push via GitHub Actions)FIREBASE_SERVICE_ACCOUNT_REDDY_WORLD secret in GitHub repository settingsNote: Firebase hosting serves from
dist/ with SPA rewrite rules (all routes → /index.html)
import {css, html, LitElement} from 'lit'; import {customElement, property} from 'lit/decorators.js'; import langCSS from "../css/langCSS"; import mainCSS from "../css/mainCSS"; // or mainCSS-refined @customElement('my-element') export class MyElement extends LitElement { @property({type: String}) myProp = 'default'; static get styles() { return [langCSS, mainCSS, css` /* component-specific styles */ `]; } render() { return html` <div>Content here</div> `; } }
Located in
src/components/global/ and imported in src/index.html:
menu-header.ts - Top navigation bar with logo and menumenu-footer.ts - Footer with linkslang-picker.ts - Language selector componentnot-found.ts - 404 error pagemy-listener.ts - Event listener utilitiesmy-dispatcher.ts - Event dispatcher utilitiesThese components are available on all pages and handle cross-page functionality.
Import Order: Always import both
langCSS and mainCSS (or mainCSS-refined)
CSS Custom Properties (use these in components):
--gold: #c7a86d --silver: #a3b7c0 --groen: #398718 --blauw: #00aaff --zwart: #1a1a1a --wit: #fdfcfb
Spacing Scale (in mainCSS-refined):
--space-1: 0.25rem --space-2: 0.5rem --space-4: 1rem --space-8: 2rem --space-16: 4rem
Located in
src/components/ui/:
gh-button.ts - Button with 5 variants (default, primary, danger, outline, ghost)gh-card.ts - Card containergh-input.ts - Form input with validation statesgh-link.ts - Link with animationsgh-text.ts - Typography componentgh-nav.ts - Navigationgh-layout.ts - Container, Stack, Flex layoutsUsage:
<gh-button variant="primary" size="md">Click Me</gh-button> <gh-card variant="bordered" hoverable>Content</gh-card>
See
src/components/ui/README.md for full documentation.
src/index.html - Entry point, loads routing and global componentssrc/vaadin-routing.js - Route definitionssrc/components/ - All page/feature componentssrc/css/ - Shared CSS modulespublic/ - Static assets (images, fonts, etc.)public/veranderkunde/ - Separate MkDocs documentation site (don't modify)Files exist but may not be active:
src/services/firebaseService.tssrc/services/authentication/firebase.jsonTest Framework: Cucumber/Gherkin (BDD approach) with Selenium WebDriver
Run Tests:
npm test # Run all tests npm run test:ci # Run tests with fail-fast for CI
Test Structure:
src/test/resources/features/*.feature (Gherkin syntax)step_definitions/MySteps.ts (TypeScript implementations)cucumber-js.conf.jsAutomated Test Execution:
pre-commit: Runs tests before each commitpre-push: Runs build + tests before pushingSetup Git Hooks (first time):
npm install # Installs husky npm run prepare # Sets up git hooks
Current Status: Test infrastructure exists with Selenium WebDriver for browser automation. TDD/BDD patterns are configured and enforced via CI/CD.
src/components/my-page.ts with @customElement('my-page-element')vaadin-routing.js: import './components/my-page'(.*) route: { path: '/my-page', component: 'my-page-element', name: 'my-page-element' }langCSS and mainCSS-refined (or mainCSS)src/css/mainCSS-refined.ts (preferred) or src/css/mainCSS.tssrc/components/ui/my-component.tssrc/components/ui/index.tsthemeTokens and baseStyles instead of langCSS/mainCSSvaadin-routing.js./dev.sh scriptsrc/, public dir is public/, output is dist/