diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0950084..5e52805 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,6 +50,9 @@ jobs: - name: Lint app run: pnpm --filter @reineira-os/modules-app run lint + - name: Lint landing + run: pnpm --filter @reineira-os/modules-landing run lint + build: name: Build runs-on: ubuntu-latest diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..3c25dad --- /dev/null +++ b/.prettierignore @@ -0,0 +1,8 @@ +node_modules/ +dist/ +.next/ +out/ +coverage/ +pnpm-lock.yaml +CHANGELOG.md +**/next-env.d.ts diff --git a/packages/landing/.commitlintrc.js b/packages/landing/.commitlintrc.js new file mode 100644 index 0000000..0e0b4bc --- /dev/null +++ b/packages/landing/.commitlintrc.js @@ -0,0 +1,34 @@ +module.exports = { + extends: ['@commitlint/config-conventional'], + rules: { + 'type-enum': [ + 2, + 'always', + [ + 'feat', + 'fix', + 'docs', + 'style', + 'refactor', + 'perf', + 'test', + 'build', + 'ci', + 'chore', + 'revert', + 'Feature', // Allow "Feature" as a type + 'feature', // Allow "feature" as a type + 'Bugfix', + 'bugfix', + 'Hotfix', + 'hotfix', + 'Release', + 'release', + ], + ], + 'subject-case': [0], // Disable subject case checking + 'subject-empty': [0], // Disable subject empty checking + 'type-empty': [0], // Disable type empty checking + 'header-max-length': [0], // Disable header max length + }, +} diff --git a/packages/landing/.env.example b/packages/landing/.env.example new file mode 100644 index 0000000..2c61f60 --- /dev/null +++ b/packages/landing/.env.example @@ -0,0 +1,5 @@ +# Waitlist submission URL (Google Apps Script) +NEXT_PUBLIC_WAITLIST_URL=https://script.google.com/macros/s/YOUR_SCRIPT_ID/exec + +# Fathom Analytics site ID +NEXT_PUBLIC_FATHOM_SITE_ID=YOUR_SITE_ID diff --git a/packages/landing/.gitignore b/packages/landing/.gitignore new file mode 100644 index 0000000..1c1cf3e --- /dev/null +++ b/packages/landing/.gitignore @@ -0,0 +1,42 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.next +out +.DS_Store +dist +dist-ssr +coverage +*.local +.eslintcache +.vite_cache + +# TypeScript incremental build cache +*.tsbuildinfo + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# Sentry Auth Token +.eslintcache +.env.sentry-build-plugin + +# Performance testing +.lighthouseci diff --git a/packages/landing/.prettierrc b/packages/landing/.prettierrc new file mode 100644 index 0000000..5c2540b --- /dev/null +++ b/packages/landing/.prettierrc @@ -0,0 +1,10 @@ +{ + "semi": false, + "singleQuote": true, + "trailingComma": "es5", + "tabWidth": 2, + "useTabs": false, + "printWidth": 120, + "endOfLine": "lf", + "htmlWhitespaceSensitivity": "ignore" +} diff --git a/packages/landing/.stylelintrc.cjs b/packages/landing/.stylelintrc.cjs new file mode 100644 index 0000000..4d60224 --- /dev/null +++ b/packages/landing/.stylelintrc.cjs @@ -0,0 +1,40 @@ +module.exports = { + plugins: ['stylelint-scss'], + extends: ['stylelint-config-recommended-scss', 'stylelint-config-recommended-vue/scss'], + rules: { + 'no-duplicate-selectors': null, + indentation: null, + 'no-descending-specificity': null, + 'at-rule-empty-line-before': null, + 'custom-property-empty-line-before': null, + 'declaration-empty-line-before': null, + 'max-nesting-depth': null, + 'value-keyword-case': null, + 'color-hex-length': ['long'], + 'color-hex-case': 'lower', + 'color-named': 'never', + 'declaration-block-single-line-max-declarations': [0], + 'selector-max-compound-selectors': 6, + 'selector-class-pattern': null, + 'media-feature-name-no-unknown': null, + 'selector-pseudo-element-no-unknown': [ + true, + { + ignorePseudoElements: ['v-deep'], + }, + ], + 'scss/dollar-variable-colon-space-after': ['always-single-line'], + 'scss/at-function-pattern': null, + 'scss/at-mixin-pattern': null, + 'scss/dollar-variable-pattern': null, + 'scss/percent-placeholder-pattern': null, + 'scss/at-mixin-argumentless-call-parentheses': 'never', + 'scss/no-duplicate-dollar-variables': true, + 'property-no-unknown': [ + true, + { + ignoreProperties: ['field-sizing'], + }, + ], + }, +} diff --git a/packages/landing/CLAUDE.md b/packages/landing/CLAUDE.md new file mode 100644 index 0000000..fa37049 --- /dev/null +++ b/packages/landing/CLAUDE.md @@ -0,0 +1,83 @@ +# Landing Template — Conventions + +> Generated project conventions. Copied into `/packages/landing/` on `/scaffold-landing`. + +## Page structure is canonical — never change it + +This template is a **1:1 clone** of the reference landing (`web-landing-app`). The page set, +component sequence, block roles, markup, and animations are **fixed across every venture**. + +**What varies per venture:** + +- Token system (`branding.accent` → 9-step scale + hover/bg/border variants; `branding.fontSans` + / `fontMono`; `branding.borderRadius`; `branding.borderWidth`). +- Text content (every string in every slot of `src/content/site.ts`). +- Image URLs (replace `src: null` → real asset, or keep `null` for `[IMAGE PLACEHOLDER]`). + +**What never varies:** + +- Set of pages (`/`, `/mobile`, `/business`, `/pricing`, `/blog`, `/contact`, `/privacy`, + `/terms`). +- Order of components on each page. +- Role/goal/markup/animation of each component. +- Component internals (don't edit files in `src/components/*` — edit `site.ts`). + +**Missing content** → `lorem(kind)` helper for text, `ImagePlaceholder` for images. +**Excess content in brief** → silently ignore. Data overload hurts conversion. + +## Token system + +`site.ts` `branding.accent` (hex) → +`src/lib/accent-scale.ts` `accentCssOverrides(hex)` → +`src/app/layout.tsx` injects `