diff --git a/CHANGELOG.md b/CHANGELOG.md index 09aeacc..80c59e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,48 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). --- +## [0.9.1] — 2026-05-21 + +### Changed + +- **HomePage** — device tabs section: removed iOS/Android tab buttons and Android panel; content now static; removed tab-switching JS; replaced phone mockup with `armarium_image.jpg` (`rounded-2xl shadow-md`, 75% width) +- **HomePage** — bottom split section: replaced Flowbite CDN images with `content_image.jpg` (75% width, centred) +- **HomePage** — CTA section: updated description to "Kostenlos mitmachen und sofort loslegen."; removed Login button, register-only +- **AboutPage** — full i18n of team and FAQ sections (all 4 locales): new keys `about.team.title`, `about.team.desc1/2`, `about.founder.role`, `about.founder.bio`, `about.faq.title`, `about.faq.q1–q4`, `about.faq.a1–a4` +- **AboutPage** — replaced Flowbite placeholder avatar with local `about_photo.jpg`; updated bio text and role to "Founder"; replaced all social icons with Armarium LinkedIn only +- **AboutPage** — replaced all Flowbite placeholder text (team description, FAQ) with Armarium-specific content via i18n + +### Added + +- `src/assets/armarium_image.jpg` — app screenshot used in homepage feature section +- `src/assets/content_image.jpg` — feature illustration used in homepage bottom split +- `src/assets/about_photo.jpg` — founder profile photo used on about page + +--- + +## [0.9.0] — 2026-05-20 + +### Changed + +- **HomePage** — complete redesign with Flowbite layout: + - Hero: Flowbite split-section (text left, `header_img.jpg` right with rounded corners + shadow), removed trust bar and Badge chip + - Added device tabs section (iOS/Android, vanilla JS tab switching, phone mockup, feature list + split image) + - Added blog preview section (3-column: featured post with image left, 2× 3 posts right, dummy fallback entries) +- **FeaturesIndexPage** — replaced old Card grid with Flowbite 4-column feature card grid; removed Badge chip from hero +- **AboutPage** — removed "Unsere Mission" and "Unsere Werte" sections; removed hero Badge chip; added Flowbite team section (3 profiles) and native `
/` FAQ +- **ContactPage** — replaced custom form with Flowbite contact form + 3 contact info blocks; removed hero Badge chip +- **BlogIndexPage** — complete rewrite with Flowbite 3-column card grid; restored hero; added CTA section before footer; removed Badge chip, tag filter, featured/regular split +- **Footer** — renamed "App" → "Produkt" (all 4 locales); added LinkedIn round icon link; restructured to 2-column layout (Produkt + Legal) +- **URL slug** — `/projects` renamed to `/features` for DE locale (`nav.features.href` in `ui.ts`, `nav.config.ts`) + +### Removed + +- Feature detail pages (`/features/[slug].astro`) and all 6 MDX files in `src/content/projects/` +- Trust bar ("Made in Zürich", privacy/free badges) from HomePage +- Badge/chip elements from hero sections on HomePage, FeaturesIndexPage, AboutPage, ContactPage + +--- + ## [0.8.1] — 2026-04-14 ### Changed diff --git a/README.md b/README.md deleted file mode 100644 index ddb2df1..0000000 --- a/README.md +++ /dev/null @@ -1,707 +0,0 @@ -

- Astro Rocket -

- -

- Astro Rocket — A production-ready Astro 6 starter theme. Change the text, launch your site. -

- -

- Astro - Tailwind CSS - TypeScript - License - Star on GitHub - Visitors -

- ---- - -## Overview - -Astro Rocket is a **launch-ready starter theme** for web designers, developers, bloggers, and anyone who needs a portfolio website. Every page is already built and styled — you change the text and content, and your site is ready to go live. - -It ships with a full blog, a complete component library, a built-in SEO layer, dark mode, a contact form, and 12 colour themes you can switch with one click. It's built on Astro 6 and Tailwind CSS v4. - -**[Live demo → astrorocket.dev](https://astrorocket.dev)** · **[Built by Hans Martens → hansmartens.dev](https://hansmartens.dev)** - -> **Astro Rocket is a fork of [Velocity](https://github.com/southwellmedia/velocity) by [Southwell Media](https://southwellmedia.com).** Velocity is the foundation — a powerful Astro boilerplate with a comprehensive design system and component library. Full credit to the Southwell Media team for that work. Astro Rocket builds on it with a different goal: a complete, ready-to-launch website where you only change the text to make it your own. - ---- - -## What changed from Velocity - -The following changes were made to the free Velocity theme to create Astro Rocket: - -| Change | Velocity | Astro Rocket | -|--------|----------|--------------| -| **Theme switching** | Edit a CSS import file and rebuild | 12 colour swatches in the header — click one and the logo badge, blog images, and every brand color update live on screen. No file edits, no rebuilds. Selector can be removed from the header once you've chosen a color. | -| **Colour themes** | 1 default theme | 12 Tailwind-based themes — all 12 shown as swatches in the header selector (Orange, Amber, Lime, Emerald, Teal, Cyan, Sky, Blue, Indigo, Violet, Purple, Magenta) | -| **Logo badge** | Requires a custom logo file | Auto-generated monogram badge — first letter of your site name on brand color, live-updates with active theme | -| **Favicon** | Static file to replace manually | Auto-generated SVG favicon — first letter + brand color, pre-rendered at build time from `site.config.ts`, no design tools needed | -| **Blog image gradients** | Plain image containers | Every blog cover and card uses a brand-color gradient background that updates live when the active theme changes | -| **Icon system** | Basic SVG `Icon` component | Unified `Icon` component powered by Iconify — 350+ Lucide UI icons + 3000+ Simple Icons brand icons | -| **Typing effect** | Not included | Hero section includes an animated typing effect | -| **Dark mode storage** | `localStorage` | `sessionStorage` — resets to dark on every new tab/session (see [why](#dark-mode)) | -| **Target audience** | Developers & agencies | Web designers, developers, bloggers, and portfolio sites | -| **Ready to launch** | Boilerplate starting point | Fully styled pages — replace the text and your site is live | -| **Maintained by** | Southwell Media | Hans Martens | - ---- - -## Key Features - -| Feature | Description | -|---------|-------------| -| **Astro 6** | Latest version with Content Layer API, security features, and performance optimizations | -| **Tailwind CSS v4** | CSS-first configuration with OKLCH color system and fluid typography | -| **12 Colour Themes** | All 12 colour swatches are shown in the header dropdown — click one and the logo badge, blog image gradients, and every brand color update live instantly. No file edits, no rebuilds. The selector can be removed from the header once you've settled on a color. | -| **Scroll Progress Bar** | A thin 2px brand-coloured bar on the header edge that fills as you scroll. Enabled on the homepage (above the floating header), blog index, and post pages (below the solid header). Controlled via `showScrollProgress` and `scrollProgressPosition` props on the Header component. | -| **Design Tokens** | Three-tier token architecture (reference → semantic → component) | -| **57 Components** | 31 UI, 7 patterns, 1 hero, 4 layout, 4 blog, 7 landing, 3 SEO — all accessible with TypeScript | -| **Auto Logo & Favicon** | First letter of your site name on brand color — generated automatically from `site.config.ts`, no design tools needed | -| **Icon System** | Unified `Icon` component (Astro + React) — 350+ [Lucide](https://lucide.dev) UI icons and 3000+ [Simple Icons](https://simpleicons.org) brand icons via Iconify | -| **Typing Effect** | Animated typing effect in the hero section | -| **Page Animations** | Smooth page transitions via Astro View Transitions, scroll-triggered counter and score animations, scroll-reactive header, card hover effects, and a full suite of UI micro-animations — all with reduced-motion support | -| **SEO Toolkit** | Meta tags, JSON-LD structured data, sitemap, and robots.txt | -| **Static OG Image** | A polished default Open Graph image serves as social preview for all pages — no build-time generation required | -| **Dark Mode** | Dark-first design with `sessionStorage` persistence | -| **Content Collections** | Type-safe blog, pages, authors, and FAQs with Zod validation | -| **API Routes** | Contact form and newsletter endpoints with validation | -| **React Islands** | Optional client-side interactivity where needed | - -### Internationalization (i18n) - -The base theme is i18n-ready with locale-aware content collection schemas. Full i18n support with language routing and a `LanguageSwitcher` component can be added via the **[create-velocity-astro](https://github.com/southwellmedia/create-velocity-astro)** CLI from Southwell Media. - ---- - -## Quick Start - -### Prerequisites - -- **Node.js 22.12.0+** (required for Astro 6) -- **pnpm 9.x** (recommended) or npm/yarn - -### Installation - -```bash -# Clone the repository -git clone https://github.com/hansmartens68/astro-rocket.git my-project -cd my-project - -# Install dependencies -pnpm install - -# Copy environment variables -cp .env.example .env - -# Start development server -pnpm dev -``` - -Visit `http://localhost:4321` to see your site. - ---- - -## Project Structure - -``` -astro-rocket/ -├── public/ # Static assets (fonts, favicon) -├── src/ -│ ├── assets/ # Images and icons (processed by Astro) -│ ├── components/ -│ │ ├── ui/ # UI component library (31 components) -│ │ │ ├── form/ # Button, Input, Textarea, Select, Checkbox, Radio, Switch -│ │ │ ├── data-display/ # Card, Badge, Avatar, Table, Pagination, Progress, Skeleton -│ │ │ ├── feedback/ # Alert, Toast, Tooltip -│ │ │ ├── overlay/ # Dialog, Dropdown, Tabs, VerticalTabs, Accordion -│ │ │ ├── layout/ # Separator -│ │ │ ├── primitives/ # Icon -│ │ │ ├── content/ # CodeBlock -│ │ │ └── marketing/ # Logo, CTA, NpmCopyButton, SocialProof, TerminalDemo -│ │ ├── patterns/ # Composed patterns (ContactForm, SearchInput, StatCard, etc.) -│ │ ├── layout/ # Header, Footer, Navigation, ThemeToggle, ThemeSelector -│ │ ├── seo/ # SEO, JsonLd, Breadcrumbs -│ │ ├── blog/ # Blog-specific components -│ │ └── landing/ # Landing page components -│ ├── content/ # Content collections -│ │ ├── blog/ # Blog posts (en/, es/, fr/) -│ │ ├── projects/ # Portfolio project pages -│ │ ├── authors/ # Author profiles -│ │ └── faqs/ # FAQ entries -│ ├── layouts/ # Page layouts -│ ├── lib/ # Utilities (schema, cn) -│ ├── pages/ # Routes and API endpoints -│ │ ├── api/ # Contact, newsletter endpoints -│ │ └── blog/ # Blog routes -│ ├── styles/ # Global CSS and design tokens -│ │ ├── tokens/ # colors.css, typography.css, spacing.css -│ │ └── themes/ # 12 colour theme files -│ └── config/ # Site and navigation configuration -├── astro.config.mjs # Astro configuration -├── package.json -└── tsconfig.json -``` - ---- - -## Commands - -| Command | Description | -|---------|-------------| -| `pnpm dev` | Start development server with hot reload | -| `pnpm build` | Build for production | -| `pnpm preview` | Preview production build locally | -| `pnpm check` | Run Astro type checker | -| `pnpm lint` | Run ESLint | -| `pnpm lint:fix` | Fix ESLint issues | -| `pnpm format` | Format code with Prettier | -| `pnpm format:check` | Check code formatting | -| `pnpm test` | Run Vitest tests | -| `pnpm test:e2e` | Run Playwright E2E tests | - ---- - -## Configuration - -### Site Configuration - -Edit `src/config/site.config.ts`: - -```typescript -const siteConfig = { - name: 'Your Site Name', - description: 'Your site description for SEO', - url: 'https://yoursite.com', - ogImage: '/og-default.svg', - author: 'Your Name', - email: 'hello@yoursite.com', - twitter: { - site: '@yourhandle', - creator: '@yourhandle', - }, -}; -``` - -### Environment Variables - -Create a `.env` file from `.env.example`: - -```bash -# Required -SITE_URL=https://yoursite.com - -# Optional - Analytics -PUBLIC_GA_MEASUREMENT_ID=G-XXXXXXXXXX -PUBLIC_GTM_ID=GTM-XXXXXXX - -# Optional - Verification -GOOGLE_SITE_VERIFICATION=your-code -BING_SITE_VERIFICATION=your-code -``` - ---- - -## Design System - -Astro Rocket uses a three-tier design token system with OKLCH colors for perceptual uniformity: - -1. **Primitives** (`src/styles/tokens/primitives.css`) — raw color scales (gray, brand, status) -2. **Semantic tokens** (`src/styles/themes/*.css`) — purpose-based mappings (background, foreground, border, etc.) -3. **Tailwind** (`src/styles/global.css`) — `@theme` directives that expose tokens as utility classes - -### Switching Themes - -Astro Rocket ships with 12 colour themes, all based on Tailwind's color palette. All 12 are shown as colour swatches in the header dropdown (`ThemeSelectorDropdown`) on desktop and in the mobile menu (`ThemeSelector`). Clicking a swatch applies the theme instantly — the logo badge, blog image gradients, and every brand color on the page update live. No file edits, no rebuilds. This is the key difference from Velocity, where switching theme requires editing a CSS import file and rebuilding. - -The 12 themes in order: Orange, Amber, Lime, Emerald, Teal, Cyan, Sky, Blue (default), Indigo, Violet, Purple, and Magenta. The `themes` array in `src/components/layout/ThemeSelector.astro` controls which swatches are shown and in what order. You can also **remove the selector from the header entirely** once you've settled on a color — just remove `showThemeSelector` from the layout file. - -The theme files live in `src/styles/themes/`: - -``` -amber.css blue.css cyan.css emerald.css -green.css indigo.css lime.css magenta.css -orange.css purple.css sky.css teal.css -violet.css -``` - -### Customizing Brand Colors - -Edit `src/styles/tokens/primitives.css` and update the `--brand-*` OKLCH values: - -```css -:root { - --brand-50: oklch(97.5% 0.02 45); /* lightest tint */ - --brand-100: oklch(94.8% 0.04 45); - --brand-200: oklch(87.5% 0.08 45); - --brand-300: oklch(77.8% 0.14 45); - --brand-400: oklch(68.5% 0.19 40); - --brand-500: oklch(62.5% 0.22 38); /* primary brand color */ - --brand-600: oklch(53.2% 0.19 38); - --brand-700: oklch(45.5% 0.16 38); - --brand-800: oklch(37.2% 0.13 38); - --brand-900: oklch(26.5% 0.09 38); -} -``` - -OKLCH values are `oklch(lightness chroma hue)`. To shift your brand to blue, change the hue from `38-45` to `~260`. Use [oklch.com](https://oklch.com) to pick colors visually. - -### Creating a New Theme - -1. Duplicate `src/styles/themes/default.css` as your starting point -2. Implement all ~35 semantic tokens for both `:root` (light) and `.dark` (dark): - - **Backgrounds**: `--background`, `--background-secondary`, `--background-tertiary`, `--background-elevated` - - **Foregrounds**: `--foreground`, `--foreground-secondary`, `--foreground-muted`, `--foreground-subtle` - - **Borders**: `--border`, `--border-strong`, `--border-subtle` - - **Interactive**: `--primary`, `--primary-hover`, `--primary-foreground`, `--secondary`, `--secondary-hover`, `--secondary-foreground`, `--accent`, `--accent-hover`, `--accent-light` - - **Surfaces**: `--muted`, `--muted-foreground`, `--card`, `--card-border`, `--input-bg`, `--input-border`, `--input-focus`, `--ring` - - **Destructive**: `--destructive`, `--destructive-foreground` - - **Gradients**: `--gradient-start`, `--gradient-end` - - **Invert sections**: `--surface-invert`, `--surface-invert-secondary`, `--surface-invert-tertiary`, `--on-invert`, `--on-invert-secondary`, `--on-invert-muted`, `--border-invert`, `--border-invert-strong` - -3. Update the import in `src/styles/tokens/colors.css` to point to your new theme file - -### Dark Mode - -Dark mode toggles via the `.dark` class on ``. The default is **dark** — the design was built dark-first and it looks great for portfolios and creative sites. - -FOUC is prevented by an inline script that reads `sessionStorage` before first paint. Use the included `ThemeToggle` component: - -```astro ---- -import ThemeToggle from '@/components/layout/ThemeToggle.astro'; ---- - - -``` - -To opt out of dark mode, remove the `.dark { ... }` block from your theme file. - -> **Why `sessionStorage` instead of `localStorage`?** This is a deliberate choice. `sessionStorage` persists the user's preference during their visit but resets when the tab is closed — so every new visit starts with the intended dark design. For a portfolio or marketing site this is the right call. For a product users return to daily (a SaaS dashboard, editor, etc.), switch to `localStorage` so the preference survives across sessions. Read the full reasoning in [this blog post](https://hansmartens.dev/blog/dark-mode-sessionstorage). - -### WCAG Contrast Requirements - -Foreground tokens are documented with their contrast ratios inline. When customizing, maintain these minimums: - -| Token | Minimum ratio | Standard | -|-------|:---:|:---:| -| `--foreground` | 7:1 | WCAG AAA | -| `--foreground-secondary` | 7:1 | WCAG AAA | -| `--foreground-muted` | 4.5:1 | WCAG AA | -| `--foreground-subtle` | 4.5:1 | WCAG AA | -| Status `-foreground` tokens | 4.5:1 | WCAG AA (on their `-light` bg) | - -### Using Design Tokens - -```astro - -
-

Hello

-
- - - -``` - ---- - -## Components - -Astro Rocket includes 57 components across 7 categories. All UI components use [class-variance-authority (CVA)](https://cva.style) for type-safe variant management. - -### UI Components (31) - -#### Form (`ui/form/`) - -| Component | Description | -|-----------|-------------| -| Button | Interactive button with primary, secondary, outline, ghost, destructive variants and loading state | -| Input | Text input with label, hint, and error states | -| Textarea | Multi-line text input | -| Select | Dropdown selection | -| Checkbox | Boolean toggle with indeterminate state | -| Radio | Single selection from group | -| Switch | Toggle switch input | - -#### Data Display (`ui/data-display/`) - -| Component | Description | -|-----------|-------------| -| Card | Content container with variant, padding, and hover options | -| Badge | Status labels and tags with contextual variants | -| Avatar | User images with fallback | -| AvatarGroup | Grouped avatar display with overlap | -| Table | Styled data table | -| Pagination | Page navigation controls | -| Progress | Progress bar indicator | -| Skeleton | Loading placeholders | - -#### Feedback (`ui/feedback/`) - -| Component | Description | -|-----------|-------------| -| Alert | Contextual feedback messages (info, success, warning, error) | -| Toast | Temporary notification messages | -| Tooltip | Hover tooltips with positioning | - -#### Overlay (`ui/overlay/`) - -| Component | Description | -|-----------|-------------| -| Dialog | Modal overlay | -| Dropdown | Menu with trigger | -| Tabs | Horizontal tabbed content panels | -| VerticalTabs | Vertical tab navigation | -| Accordion | Collapsible content sections | - -#### Layout (`ui/layout/`) - -| Component | Description | -|-----------|-------------| -| Separator | Visual divider between sections | - -#### Primitives (`ui/primitives/`) - -| Component | Description | -|-----------|-------------| -| Icon | Unified icon component (Astro + React) powered by Iconify. Supports all [Lucide](https://lucide.dev) icons (`lucide:*`) and all [Simple Icons](https://simpleicons.org) brand icons (`simple-icons:*`). Includes shorthand names for common social and brand icons. Five size variants: `xs`, `sm`, `md`, `lg`, `xl`. | - -#### Content (`ui/content/`) - -| Component | Description | -|-----------|-------------| -| CodeBlock | Syntax-highlighted code display | - -#### Marketing (`ui/marketing/`) - -| Component | Description | -|-----------|-------------| -| Logo | Auto-generated monogram badge — renders the first letter of `siteConfig.name` on the active brand color. Five sizes: `sm`, `md`, `lg`, `xl`, `2xl`. No logo file required. | -| CTA | Call-to-action sections with slot-based composition | -| NpmCopyButton | NPM install command with copy-to-clipboard | -| SocialProof | Testimonial and trust indicator cards | -| TerminalDemo | Animated terminal demonstration (React) | - -### Pattern Components (7) - -| Component | Description | -|-----------|-------------| -| ContactForm | Complete contact form with validation | -| NewsletterForm | Email subscription form | -| FormField | Reusable form field wrapper | -| SearchInput | Search input with icon | -| PasswordInput | Password input with visibility toggle | -| StatCard | Statistics display card | -| EmptyState | Empty state placeholder with icon and action | - -### Other Categories - -| Category | Count | Components | -|----------|-------|------------| -| Hero | 1 | Hero section with centered/split layouts, grid pattern, and typing effect | -| Layout | 6 | Header (with scroll progress bar), Footer, ThemeToggle, ThemeSelector, ThemeSelectorDropdown, Analytics | -| Blog | 4 | ArticleHero, BlogCard, ShareButtons, RelatedPosts | -| Landing | 5 | Credibility, LighthouseScores, TechStack, FeatureTabs, and more | -| SEO | 3 | SEO, JsonLd, Breadcrumbs | - -### Usage Example - -```astro ---- -import { Button, Input, Card } from '@/components/ui'; ---- - - - - - -``` - -### Icon Usage - -```astro ---- -import Icon from '@/components/ui/primitives/Icon/Icon.astro'; ---- - - - - - - - - - - - - - - - -``` - -All UI components are imported via barrel exports from `@/components/ui`. View all components at `/components` in development. - ---- - -## Content Management - -### Blog Posts - -Create posts in `src/content/blog/[locale]/`: - -```markdown ---- -title: "Your Post Title" -description: "Brief description for SEO" -publishedAt: 2026-01-30 -author: "Author Name" -tags: ["astro", "tutorial"] -locale: en ---- - -Your content here... -``` - -### Querying Content - -```astro ---- -import { getCollection } from 'astro:content'; - -const posts = await getCollection('blog', ({ data }) => { - return import.meta.env.PROD ? !data.draft : true; -}); ---- -``` - ---- - -## SEO - -### Automatic Features - -- **Meta tags**: Title, description, canonical URL -- **Open Graph**: Complete OG tags for social sharing -- **Twitter Cards**: Large image cards -- **JSON-LD**: WebSite, Organization, BlogPosting, Breadcrumb, FAQ schemas -- **Sitemap**: Auto-generated at `/sitemap-index.xml` -- **robots.txt**: Dynamic generation with sitemap reference -- **OG Images**: A static default OG image serves all pages and blog posts - -### Using the SEO Component - -```astro ---- -import SEO from '@/components/seo/SEO.astro'; ---- - - - - -``` - -### OG Image - -A static default OG image (`public/og-default.svg`) serves as the social preview for all pages. The path is set via `ogImage` in `src/config/site.config.ts`. To use a custom image for a specific page, pass it as the `image` prop to the layout component. - ---- - -## API Routes - -### Contact Form - -**POST** `/api/contact` - -```typescript -// Request (FormData) -{ - name: string, // 2-100 chars - email: string, // Valid email - subject: string, // Required - message: string, // 10-5000 chars - honeypot: string // Must be empty (spam check) -} - -// Response -{ success: true } -// or -{ success: false, errors: { field: ["message"] } } -``` - -### Newsletter - -**POST** `/api/newsletter` - -```typescript -// Request (FormData) -{ email: string } - -// Response -{ success: true } -// or -{ success: false, error: "message" } -``` - ---- - -## Deployment - -Configuration files included for major platforms. - -### Vercel (Recommended) - -```bash -vercel -``` - -### Netlify - -```bash -netlify deploy --prod -``` - -### Cloudflare Pages - -```bash -wrangler pages deploy dist -``` - -### Static Export - -Build outputs to `dist/` for any static host: - -```bash -pnpm build -``` - ---- - -## Browser Support - -- Chrome (last 2 versions) -- Firefox (last 2 versions) -- Safari (last 2 versions) -- Edge (last 2 versions) - ---- - -## Performance - -Astro Rocket is optimized for Core Web Vitals: - -- **Lighthouse Score**: 95+ across all categories -- **Zero JavaScript** by default (islands architecture) -- **Optimized fonts** with `font-display: swap` -- **Image optimization** via Astro's built-in processing -- **Prefetching** for instant page transitions - ---- - -## Animations - -Every page in Astro Rocket includes purposeful animations that make the site feel polished and alive. All animations respect the user's `prefers-reduced-motion` setting — they are disabled automatically for users who prefer less motion. - -### Page transitions - -Astro Rocket uses Astro's built-in `` (View Transitions API) to animate between pages. Instead of a full browser reload, content fades smoothly from one page to the next. This is enabled globally in `BaseLayout.astro` and requires no per-page configuration. - -### Scroll-triggered animations - -Two components use an `IntersectionObserver` to trigger animations when elements enter the viewport: - -- **Counter animation** — the stats block on the homepage (Years Experience, Projects Delivered, etc.) counts up from zero when it scrolls into view. Each number animates with a cubic ease-out over 1.2 seconds. -- **Lighthouse score bars** — the `LighthouseScores` landing component animates its score bars into place as the section becomes visible. - -### Scroll-reactive header - -The floating header changes its appearance as the user scrolls. When the page is at the top, the header is transparent with inverted text. Once the user scrolls past 60px, the header gains a solid background and the text flips to normal colors — all driven by CSS transitions via a `data-scrolled` attribute. - -### Scroll progress bar - -A thin 2px brand-coloured bar on the header edge that grows from left to right as the user scrolls, showing reading progress at a glance. Enable it with two props on the `
` component: - -| Prop | Type | Default | What it does | -|------|------|:-------:|--------------| -| `showScrollProgress` | `boolean` | `false` | Renders the progress bar | -| `scrollProgressPosition` | `'top'` \| `'bottom'` | `'bottom'` | Edge of the header where the bar sits | - -The bar is enabled by default on three page types: the **homepage** (above the floating header), the **blog index**, and **individual blog posts** (both below the solid bar header). Use `scrollProgressPosition="top"` on a floating capsule header and `'bottom'` on a solid bar header. The bar colour always matches `--color-brand-500` and updates instantly when the visitor switches themes. - -### Card hover effects - -Cards throughout the site lift slightly on hover (`-translate-y-1`) and gain a subtle shadow. This is a Tailwind utility applied consistently to all interactive cards. - -### UI micro-animations - -The full animation library is defined in `src/styles/global.css`. These classes are used by components throughout the site: - -| Class | What it does | -|-------|-------------| -| `animate-fade-in` | Fades an element from transparent to visible (0.5s ease-out) | -| `animate-slide-up` | Slides an element up from 12px below while fading in (0.5s ease-out) | -| `animate-slide-down` | Slides an element down from 12px above while fading in (0.5s ease-out) | -| `animate-dropdown-in` | Slides and scales a dropdown menu into view (0.2s spring) | -| `animate-dropdown-out` | Collapses a dropdown menu out of view (0.15s) | -| `animate-sheet-up` | Slides a bottom sheet up from off-screen (0.25s spring) | -| `animate-menu-down` | Slides the mobile navigation drawer open (0.25s spring) | -| `animate-tab-enter` | Crossfades tab panel content when switching tabs | -| `animate-toast-in` | Slides a toast notification in from the right (350ms spring) | -| `animate-tooltip-in` | Fades and scales a tooltip into view | -| `animate-pulse` | Breathing pulse for skeleton loading states | -| `animate-spin` | Continuous rotation for loading spinners | -| `animate-shake` | Brief shake for error feedback (400ms) | - -Animation delay utilities (`.delay-0` through `.delay-5`, in 50ms steps) let you stagger multiple elements into view. - ---- - -## Contributing - -Contributions are welcome! - -1. Fork the repository -2. Create a feature branch (`git checkout -b feature/amazing-feature`) -3. Commit your changes (`git commit -m 'Add amazing feature'`) -4. Push to the branch (`git push origin feature/amazing-feature`) -5. Open a Pull Request - -Please ensure your code passes linting (`pnpm lint`) and type checking (`pnpm check`) before submitting. - ---- - -## License - -MIT License — see [LICENSE](LICENSE) for details. - ---- - -## Links - -- [Astro Rocket on GitHub](https://github.com/hansmartens68/astro-rocket) -- [Velocity — the original theme](https://github.com/southwellmedia/velocity) by [Southwell Media](https://southwellmedia.com) -- [Astro Documentation](https://docs.astro.build) -- [Tailwind CSS v4](https://tailwindcss.com/docs) - ---- - -**Astro Rocket** is designed and maintained by [Hans Martens](https://hansmartens.dev). -Built on [Velocity](https://github.com/southwellmedia/velocity) — the original theme by [Southwell Media](https://southwellmedia.com). diff --git a/component-registry.json b/component-registry.json deleted file mode 100644 index 4ab503e..0000000 --- a/component-registry.json +++ /dev/null @@ -1,638 +0,0 @@ -{ - "$schema": "./component-registry.schema.json", - "version": "2.0.0", - "categories": { - "ui": { - "name": "UI Components", - "description": "Core building blocks - buttons, forms, cards, dialogs", - "subcategories": { - "form": { - "name": "Form", - "description": "Form input components - buttons, inputs, selects" - }, - "data-display": { - "name": "Data Display", - "description": "Components for displaying data - cards, badges, tables" - }, - "feedback": { - "name": "Feedback", - "description": "User feedback components - alerts, toasts, tooltips" - }, - "overlay": { - "name": "Overlay", - "description": "Overlay components - dialogs, dropdowns, tabs" - }, - "layout": { - "name": "Layout", - "description": "Layout components - separators, dividers" - }, - "primitives": { - "name": "Primitives", - "description": "Fundamental components used across the system" - }, - "content": { - "name": "Content", - "description": "Content display components" - }, - "marketing": { - "name": "Marketing", - "description": "Marketing and landing page components" - } - } - }, - "layout": { - "name": "Layout Components", - "description": "Page structure components - header, footer, navigation" - }, - "patterns": { - "name": "Patterns", - "description": "Reusable form and UI patterns" - }, - "hero": { - "name": "Hero", - "description": "Flexible hero section component" - } - }, - "utilities": { - "cn": { - "name": "cn utility", - "description": "Tailwind CSS class merging utility", - "files": ["src/lib/cn.ts"], - "npm": ["clsx", "tailwind-merge"] - } - }, - "components": { - "button": { - "name": "Button", - "category": "ui", - "subcategory": "form", - "files": [ - "src/components/ui/form/Button/Button.astro", - "src/components/ui/form/Button/Button.tsx", - "src/components/ui/form/Button/button.variants.ts", - "src/components/ui/form/Button/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "input": { - "name": "Input", - "category": "ui", - "subcategory": "form", - "files": [ - "src/components/ui/form/Input/Input.astro", - "src/components/ui/form/Input/Input.tsx", - "src/components/ui/form/Input/input.variants.ts", - "src/components/ui/form/Input/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "textarea": { - "name": "Textarea", - "category": "ui", - "subcategory": "form", - "files": [ - "src/components/ui/form/Textarea/Textarea.astro", - "src/components/ui/form/Textarea/Textarea.tsx", - "src/components/ui/form/Textarea/textarea.variants.ts", - "src/components/ui/form/Textarea/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "select": { - "name": "Select", - "category": "ui", - "subcategory": "form", - "files": [ - "src/components/ui/form/Select/Select.astro", - "src/components/ui/form/Select/Select.tsx", - "src/components/ui/form/Select/select.variants.ts", - "src/components/ui/form/Select/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "checkbox": { - "name": "Checkbox", - "category": "ui", - "subcategory": "form", - "files": [ - "src/components/ui/form/Checkbox/Checkbox.astro", - "src/components/ui/form/Checkbox/Checkbox.tsx", - "src/components/ui/form/Checkbox/checkbox.variants.ts", - "src/components/ui/form/Checkbox/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "radio": { - "name": "Radio", - "category": "ui", - "subcategory": "form", - "files": [ - "src/components/ui/form/Radio/Radio.astro", - "src/components/ui/form/Radio/Radio.tsx", - "src/components/ui/form/Radio/radio.variants.ts", - "src/components/ui/form/Radio/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "switch": { - "name": "Switch", - "category": "ui", - "subcategory": "form", - "files": [ - "src/components/ui/form/Switch/Switch.astro", - "src/components/ui/form/Switch/Switch.tsx", - "src/components/ui/form/Switch/switch.variants.ts", - "src/components/ui/form/Switch/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "card": { - "name": "Card", - "category": "ui", - "subcategory": "data-display", - "files": [ - "src/components/ui/data-display/Card/Card.astro", - "src/components/ui/data-display/Card/Card.tsx", - "src/components/ui/data-display/Card/card.variants.ts", - "src/components/ui/data-display/Card/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "badge": { - "name": "Badge", - "category": "ui", - "subcategory": "data-display", - "files": [ - "src/components/ui/data-display/Badge/Badge.astro", - "src/components/ui/data-display/Badge/badge.variants.ts", - "src/components/ui/data-display/Badge/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "avatar": { - "name": "Avatar", - "category": "ui", - "subcategory": "data-display", - "files": [ - "src/components/ui/data-display/Avatar/Avatar.astro", - "src/components/ui/data-display/Avatar/avatar.variants.ts", - "src/components/ui/data-display/Avatar/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "avatar-group": { - "name": "AvatarGroup", - "category": "ui", - "subcategory": "data-display", - "files": [ - "src/components/ui/data-display/AvatarGroup/AvatarGroup.astro", - "src/components/ui/data-display/AvatarGroup/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": ["avatar"] - }, - "premium": false - }, - "table": { - "name": "Table", - "category": "ui", - "subcategory": "data-display", - "files": [ - "src/components/ui/data-display/Table/Table.astro", - "src/components/ui/data-display/Table/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "pagination": { - "name": "Pagination", - "category": "ui", - "subcategory": "data-display", - "files": [ - "src/components/ui/data-display/Pagination/Pagination.astro", - "src/components/ui/data-display/Pagination/pagination.variants.ts", - "src/components/ui/data-display/Pagination/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": ["icon"] - }, - "premium": false - }, - "progress": { - "name": "Progress", - "category": "ui", - "subcategory": "data-display", - "files": [ - "src/components/ui/data-display/Progress/Progress.astro", - "src/components/ui/data-display/Progress/progress.variants.ts", - "src/components/ui/data-display/Progress/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "skeleton": { - "name": "Skeleton", - "category": "ui", - "subcategory": "data-display", - "files": [ - "src/components/ui/data-display/Skeleton/Skeleton.astro", - "src/components/ui/data-display/Skeleton/skeleton.variants.ts", - "src/components/ui/data-display/Skeleton/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "alert": { - "name": "Alert", - "category": "ui", - "subcategory": "feedback", - "files": [ - "src/components/ui/feedback/Alert/Alert.astro", - "src/components/ui/feedback/Alert/alert.variants.ts", - "src/components/ui/feedback/Alert/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "toast": { - "name": "Toast", - "category": "ui", - "subcategory": "feedback", - "files": [ - "src/components/ui/feedback/Toast/Toast.astro", - "src/components/ui/feedback/Toast/Toast.tsx", - "src/components/ui/feedback/Toast/ToastDemo.tsx", - "src/components/ui/feedback/Toast/toast.variants.ts", - "src/components/ui/feedback/Toast/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "tooltip": { - "name": "Tooltip", - "category": "ui", - "subcategory": "feedback", - "files": [ - "src/components/ui/feedback/Tooltip/Tooltip.astro", - "src/components/ui/feedback/Tooltip/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "dialog": { - "name": "Dialog", - "category": "ui", - "subcategory": "overlay", - "files": [ - "src/components/ui/overlay/Dialog/Dialog.astro", - "src/components/ui/overlay/Dialog/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "dropdown": { - "name": "Dropdown", - "category": "ui", - "subcategory": "overlay", - "files": [ - "src/components/ui/overlay/Dropdown/Dropdown.astro", - "src/components/ui/overlay/Dropdown/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "tabs": { - "name": "Tabs", - "category": "ui", - "subcategory": "overlay", - "files": [ - "src/components/ui/overlay/Tabs/Tabs.astro", - "src/components/ui/overlay/Tabs/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "vertical-tabs": { - "name": "VerticalTabs", - "category": "ui", - "subcategory": "overlay", - "files": [ - "src/components/ui/overlay/VerticalTabs/VerticalTabs.astro", - "src/components/ui/overlay/VerticalTabs/VerticalTabs.tsx", - "src/components/ui/overlay/VerticalTabs/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "accordion": { - "name": "Accordion", - "category": "ui", - "subcategory": "overlay", - "files": [ - "src/components/ui/overlay/Accordion/Accordion.astro", - "src/components/ui/overlay/Accordion/accordion.variants.ts", - "src/components/ui/overlay/Accordion/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": ["icon"] - }, - "premium": false - }, - "separator": { - "name": "Separator", - "category": "ui", - "subcategory": "layout", - "files": [ - "src/components/ui/layout/Separator/Separator.astro", - "src/components/ui/layout/Separator/separator.variants.ts", - "src/components/ui/layout/Separator/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "icon": { - "name": "Icon", - "category": "ui", - "subcategory": "primitives", - "files": [ - "src/components/ui/primitives/Icon/Icon.astro", - "src/components/ui/primitives/Icon/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "code-block": { - "name": "CodeBlock", - "category": "ui", - "subcategory": "content", - "files": [ - "src/components/ui/content/CodeBlock/CodeBlock.astro", - "src/components/ui/content/CodeBlock/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "logo": { - "name": "Logo", - "category": "ui", - "subcategory": "marketing", - "files": [ - "src/components/ui/marketing/Logo/Logo.astro", - "src/components/ui/marketing/Logo/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "cta": { - "name": "CTA", - "category": "ui", - "subcategory": "marketing", - "files": [ - "src/components/ui/marketing/CTA/CTA.astro", - "src/components/ui/marketing/CTA/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": ["logo"] - }, - "premium": false - }, - "npm-copy-button": { - "name": "NpmCopyButton", - "category": "ui", - "subcategory": "marketing", - "files": [ - "src/components/ui/marketing/NpmCopyButton/NpmCopyButton.astro", - "src/components/ui/marketing/NpmCopyButton/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": ["icon"] - }, - "premium": false - }, - "social-proof": { - "name": "SocialProof", - "category": "ui", - "subcategory": "marketing", - "files": [ - "src/components/ui/marketing/SocialProof/SocialProof.astro", - "src/components/ui/marketing/SocialProof/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "terminal-demo": { - "name": "TerminalDemo", - "category": "ui", - "subcategory": "marketing", - "files": [ - "src/components/ui/marketing/TerminalDemo/TerminalDemo.tsx", - "src/components/ui/marketing/TerminalDemo/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "contact-form": { - "name": "ContactForm", - "category": "patterns", - "files": ["src/components/patterns/ContactForm.astro"], - "dependencies": { - "utilities": ["cn"], - "components": ["input", "textarea", "button"] - }, - "premium": false - }, - "newsletter-form": { - "name": "NewsletterForm", - "category": "patterns", - "files": ["src/components/patterns/NewsletterForm.astro"], - "dependencies": { - "utilities": ["cn"], - "components": ["input", "button"] - }, - "premium": false - }, - "form-field": { - "name": "FormField", - "category": "patterns", - "files": ["src/components/patterns/FormField.astro"], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "search-input": { - "name": "SearchInput", - "category": "patterns", - "files": ["src/components/patterns/SearchInput.astro"], - "dependencies": { - "utilities": ["cn"], - "components": ["input"] - }, - "premium": false - }, - "password-input": { - "name": "PasswordInput", - "category": "patterns", - "files": ["src/components/patterns/PasswordInput.astro"], - "dependencies": { - "utilities": ["cn"], - "components": ["input", "icon"] - }, - "premium": false - }, - "stat-card": { - "name": "StatCard", - "category": "patterns", - "files": ["src/components/patterns/StatCard.astro"], - "dependencies": { - "utilities": ["cn"], - "components": ["card", "icon"] - }, - "premium": false - }, - "empty-state": { - "name": "EmptyState", - "category": "patterns", - "files": ["src/components/patterns/EmptyState.astro"], - "dependencies": { - "utilities": ["cn"], - "components": ["icon", "button"] - }, - "premium": false - }, - "hero": { - "name": "Hero", - "category": "hero", - "files": [ - "src/components/hero/Hero.astro", - "src/components/hero/hero.variants.ts", - "src/components/hero/index.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": [] - }, - "premium": false - }, - "header": { - "name": "Header", - "category": "layout", - "files": [ - "src/components/layout/Header.astro", - "src/components/layout/header.variants.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": ["button", "icon", "logo"] - }, - "premium": false - }, - "footer": { - "name": "Footer", - "category": "layout", - "files": [ - "src/components/layout/Footer.astro", - "src/components/layout/footer.variants.ts" - ], - "dependencies": { - "utilities": ["cn"], - "components": ["icon", "logo"] - }, - "premium": false - } - } -} diff --git a/component-registry.schema.json b/component-registry.schema.json deleted file mode 100644 index 45411da..0000000 --- a/component-registry.schema.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/hansmartens68/astro--rocket/component-registry.schema.json", - "title": "Astro Rocket Component Registry", - "description": "Schema for the Astro Rocket component registry", - "type": "object", - "required": ["version", "categories", "utilities", "components"], - "properties": { - "$schema": { - "type": "string", - "description": "JSON schema reference" - }, - "version": { - "type": "string", - "pattern": "^\\d+\\.\\d+\\.\\d+$", - "description": "Registry version (semver)" - }, - "categories": { - "type": "object", - "description": "Component categories", - "additionalProperties": { - "$ref": "#/$defs/category" - } - }, - "utilities": { - "type": "object", - "description": "Shared utility files", - "additionalProperties": { - "$ref": "#/$defs/utility" - } - }, - "components": { - "type": "object", - "description": "Component definitions", - "additionalProperties": { - "$ref": "#/$defs/component" - } - } - }, - "$defs": { - "category": { - "type": "object", - "required": ["name", "description"], - "properties": { - "name": { - "type": "string", - "description": "Display name of the category" - }, - "description": { - "type": "string", - "description": "Brief description of the category" - } - } - }, - "utility": { - "type": "object", - "required": ["name", "description", "files", "npm"], - "properties": { - "name": { - "type": "string", - "description": "Display name of the utility" - }, - "description": { - "type": "string", - "description": "Brief description of the utility" - }, - "files": { - "type": "array", - "items": { - "type": "string" - }, - "description": "File paths for this utility" - }, - "npm": { - "type": "array", - "items": { - "type": "string" - }, - "description": "NPM packages required by this utility" - } - } - }, - "component": { - "type": "object", - "required": ["name", "category", "files", "dependencies", "premium"], - "properties": { - "name": { - "type": "string", - "description": "Display name of the component" - }, - "category": { - "type": "string", - "description": "Category ID this component belongs to" - }, - "subcategory": { - "type": "string", - "description": "Subcategory within the main category (e.g., form, data-display, feedback)" - }, - "files": { - "type": "array", - "items": { - "type": "string" - }, - "description": "File paths for this component" - }, - "dependencies": { - "type": "object", - "required": ["utilities", "components"], - "properties": { - "utilities": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Utility IDs this component depends on" - }, - "components": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Component IDs this component depends on" - } - } - }, - "premium": { - "type": "boolean", - "description": "Whether this is a premium component" - } - } - } - } -} diff --git a/netlify.toml b/netlify.toml deleted file mode 100644 index 55daa90..0000000 --- a/netlify.toml +++ /dev/null @@ -1,30 +0,0 @@ -[build] - command = "pnpm run build" - publish = "dist" - -[build.environment] - NODE_VERSION = "22" - -[[headers]] - for = "/*" - [headers.values] - X-Frame-Options = "DENY" - X-Content-Type-Options = "nosniff" - Referrer-Policy = "strict-origin-when-cross-origin" - Strict-Transport-Security = "max-age=31536000; includeSubDomains" - -[[headers]] - for = "/fonts/*" - [headers.values] - Cache-Control = "public, max-age=31536000, immutable" - -[[headers]] - for = "/_astro/*" - [headers.values] - Cache-Control = "public, max-age=31536000, immutable" - -# Redirect rules -[[redirects]] - from = "/api/*" - to = "/.netlify/functions/:splat" - status = 200 diff --git a/src/assets/Icon.svg b/src/assets/Icon.svg new file mode 100644 index 0000000..6601b86 --- /dev/null +++ b/src/assets/Icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/Logo_vertikal.svg b/src/assets/Logo_vertikal.svg new file mode 100644 index 0000000..145f9e7 --- /dev/null +++ b/src/assets/Logo_vertikal.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/about_photo.jpg b/src/assets/about_photo.jpg new file mode 100644 index 0000000..0d27906 Binary files /dev/null and b/src/assets/about_photo.jpg differ diff --git a/src/assets/armarium_image.jpg b/src/assets/armarium_image.jpg new file mode 100644 index 0000000..99ae164 Binary files /dev/null and b/src/assets/armarium_image.jpg differ diff --git a/src/assets/content_image.jpg b/src/assets/content_image.jpg new file mode 100644 index 0000000..584ad06 Binary files /dev/null and b/src/assets/content_image.jpg differ diff --git a/src/assets/header_img.jpg b/src/assets/header_img.jpg new file mode 100644 index 0000000..041e52b Binary files /dev/null and b/src/assets/header_img.jpg differ diff --git a/src/assets/readme-hero.svg b/src/assets/readme-hero.svg deleted file mode 100644 index 25c6dfa..0000000 --- a/src/assets/readme-hero.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Astro Rocket - diff --git a/src/components/landing/AboutPage.astro b/src/components/landing/AboutPage.astro index de9c2ff..2dac15a 100644 --- a/src/components/landing/AboutPage.astro +++ b/src/components/landing/AboutPage.astro @@ -5,6 +5,8 @@ import Badge from '@/components/ui/data-display/Badge/Badge.astro'; import Card from '@/components/ui/data-display/Card/Card.astro'; import Button from '@/components/ui/form/Button/Button.astro'; import { Hero } from '@/components/hero'; +import { Image } from 'astro:assets'; +import aboutPhoto from '@/assets/about_photo.jpg'; import { useTranslations } from '@/i18n/utils'; import type { Locale } from '@/i18n/ui'; @@ -22,10 +24,6 @@ const t = useTranslations(locale); locale={locale} > - - - {t('about.badge')} -

{t('about.title.pre')} {t('about.title.accent')} @@ -33,117 +31,50 @@ const t = useTranslations(locale);

{t('about.desc')}

- -
-
-
-
-
- {t('about.mission.badge')} -

- {t('about.mission.title')} -

+ +
+
+
+

{t('about.team.title')}

+

{t('about.team.desc1')}

+

{t('about.team.desc2')}

+
+
+
+ Daniel Krähenbühl +
+

Daniel Krähenbühl

+ {t('about.founder.role')} +

{t('about.founder.bio')}

+
-

{t('about.mission.p1')}

-

{t('about.mission.p2')}

-
- -
- -
-
- -
-
-

{t('about.app.label')}

-

{t('about.app.title')}

-

{t('about.app.desc')}

-
- Angular - Budget - {t('about.privacy.label')} -
-
-
-
- - -
-
- -
-
-

{t('about.privacy.label')}

-

{t('about.privacy.title')}

-

{t('about.privacy.desc')}

-
-
-
- -
-
-
-
- {t('about.values.badge')} -

{t('about.values.title')}

-
-
-
- -
-
- + +
+
+

{t('about.faq.title')}

+
+ {([1,2,3,4] as const).map((n) => ( +
+ + {t(`about.faq.q${n}` as any)} + + +
+

{t(`about.faq.a${n}` as any)}

-
-

{t('about.v1.title')}

-

{t('about.v1.desc')}

-
-
- - -
-
- -
-
-

{t('about.v2.title')}

-

{t('about.v2.desc')}

-
-
-
- -
-
- -
-
-

{t('about.v3.title')}

-

{t('about.v3.desc')}

-
-
-
- - -
-
- - - - - - -
-
-

{t('about.v4.title')}

-

{t('about.v4.desc')}

-
-
-
+

+ ))} diff --git a/src/components/landing/BlogIndexPage.astro b/src/components/landing/BlogIndexPage.astro index d2d263b..75ea7a8 100644 --- a/src/components/landing/BlogIndexPage.astro +++ b/src/components/landing/BlogIndexPage.astro @@ -1,13 +1,12 @@ --- import PageLayout from '@/layouts/PageLayout.astro'; -import BlogCard from '@/components/blog/BlogCard.astro'; -import Badge from '@/components/ui/data-display/Badge/Badge.astro'; -import Icon from '@/components/ui/primitives/Icon/Icon.astro'; -import CTA from '@/components/ui/marketing/CTA/CTA.astro'; import { Hero } from '@/components/hero'; +import Button from '@/components/ui/form/Button/Button.astro'; +import Icon from '@/components/ui/primitives/Icon/Icon.astro'; +import BlogImageSVG from '@/components/blog/BlogImageSVG.astro'; +import { Image } from 'astro:assets'; import { getCollection } from 'astro:content'; -import siteConfig from '@/config/site.config'; -import { resolveSocialLinks } from '@/lib/utils'; +import { formatDate } from '@/lib/utils'; import { useTranslations } from '@/i18n/utils'; import type { Locale } from '@/i18n/ui'; @@ -17,23 +16,14 @@ interface Props { const { locale } = Astro.props; const t = useTranslations(locale); -const socialLinks = resolveSocialLinks(siteConfig.socialLinks); -// Get all published posts (all locales) const allPosts = await getCollection('blog', ({ data }) => { return import.meta.env.PROD ? data.draft !== true : true; }); const posts = allPosts.sort((a, b) => b.data.publishedAt.valueOf() - a.data.publishedAt.valueOf()); -const featuredPosts = posts.filter((post) => post.data.featured); -const nonFeaturedPosts = posts.filter((post) => !post.data.featured); -const regularPosts = nonFeaturedPosts.length > 0 ? nonFeaturedPosts : posts; - -const allTags = [...new Set(posts.flatMap((post) => post.data.tags))].sort(); - const getPostUrl = (postId: string) => { - // Strip locale folder prefix (e.g., "en/post-slug" → "post-slug") const slug = postId.replace(/^[a-z]{2}\//, ''); return `/blog/${slug}`; }; @@ -46,210 +36,59 @@ const getPostUrl = (postId: string) => { locale={locale} > - - - {t('blog.badge')} - -

{t('blog.title')}

-

{t('blog.desc')}

- - { - featuredPosts.length > 0 && ( - - ) - } - - -
0 ? 'bg-background' : 'bg-background-secondary', 'py-[var(--space-section-md)] border-t border-border']}> -
-
- { - featuredPosts.length > 0 && nonFeaturedPosts.length > 0 && ( -

{t('blog.allposts')}

- ) - } - - {allTags.length > 0 && ( -
- -
- - - - - +
+
+
+ {posts.map((post) => ( +
- )} -
- - { - regularPosts.length > 0 ? ( -
- {regularPosts.map((post) => ( -
- + )} +

+ {post.data.title} +

+

{post.data.description}

+
+
+ {post.data.author?.charAt(0) ?? 'A'} +
+
+
{post.data.author ?? 'Team'}
+
{formatDate(post.data.publishedAt)}
- ))} -
- ) : ( -
-
-
-

{t('blog.noposts')}

-
- ) - } - -
- - 0 && '!bg-background-secondary']}> -

{t('blog.follow.title')}

-

{t('blog.follow.desc')}

- -
- - - RSS Feed - - {socialLinks.map((link) => ( - - - {link.label} - - ))} - - - Email - + +
+
+

{t('cta.title')}

+

{t('cta.desc')}

+
+ +
- +
- - - - diff --git a/src/components/landing/ContactPage.astro b/src/components/landing/ContactPage.astro index 69f9e4a..0324252 100644 --- a/src/components/landing/ContactPage.astro +++ b/src/components/landing/ContactPage.astro @@ -1,12 +1,7 @@ --- import PageLayout from '@/layouts/PageLayout.astro'; -import Icon from '@/components/ui/primitives/Icon/Icon.astro'; -import Badge from '@/components/ui/data-display/Badge/Badge.astro'; -import Card from '@/components/ui/data-display/Card/Card.astro'; import { Hero } from '@/components/hero'; -import ContactForm from '@/components/patterns/ContactForm.astro'; import siteConfig from '@/config/site.config'; -import { resolveSocialLinks } from '@/lib/utils'; import { useTranslations } from '@/i18n/utils'; import type { Locale } from '@/i18n/ui'; @@ -16,26 +11,6 @@ interface Props { const { locale } = Astro.props; const t = useTranslations(locale); -const socialLinks = resolveSocialLinks(siteConfig.socialLinks); - -const channels = [ - { - icon: 'mail', - label: 'Email', - value: siteConfig.email, - note: t('contact.follow'), - href: `mailto:${siteConfig.email}`, - external: false, - }, - ...socialLinks.map((link) => ({ - icon: link.icon, - label: link.label, - value: link.href.replace(/^https?:\/\/(www\.)?/, ''), - note: t('contact.follow'), - href: link.href, - external: true, - })), -]; --- - - - {t('contact.badge')} - -

{t('contact.title').replace('.', '')} {t('contact.title').slice(-1)}

-

{t('contact.desc')}

- -
-
-
- - -
- -

{t('contact.form.title')}

- -
+
+
+
+
+ +
- - -
-
-

{t('contact.direct.title')}

-

{t('contact.direct.desc')}

-
- - -
- {channels.map((ch) => ( - - -
-
- -
-
-

{ch.label}

-

{ch.value}

-
- -
-
-
- ))} -
- - - -
-
- -
-
-

{siteConfig.address?.city ?? 'Zürich'}

-

{siteConfig.address?.country ?? 'Switzerland'}

-
-
-
- +
+ +
+
+ + +
+
+ + +
+
+ + +

By submitting this form you agree to our terms and conditions and our privacy policy.

+
+ + +
+
+
+ +
+

Email us:

+

Email us for general queries, including marketing and partnership opportunities.

+ {siteConfig.email} +
+
+
+ +
+

Support

+

Email us for general queries, including marketing and partnership opportunities.

+ Support center +
+
+
+ +
+

Find us:

+

{siteConfig.address?.city ?? 'Zürich'}, {siteConfig.address?.country ?? 'Switzerland'}

+
diff --git a/src/components/landing/FeaturesIndexPage.astro b/src/components/landing/FeaturesIndexPage.astro index f69ed07..14fb3c6 100644 --- a/src/components/landing/FeaturesIndexPage.astro +++ b/src/components/landing/FeaturesIndexPage.astro @@ -1,9 +1,7 @@ --- import PageLayout from '@/layouts/PageLayout.astro'; -import Icon from '@/components/ui/primitives/Icon/Icon.astro'; -import Badge from '@/components/ui/data-display/Badge/Badge.astro'; -import Card from '@/components/ui/data-display/Card/Card.astro'; import Button from '@/components/ui/form/Button/Button.astro'; +import Icon from '@/components/ui/primitives/Icon/Icon.astro'; import { Hero } from '@/components/hero'; import { getCollection } from 'astro:content'; import { useTranslations } from '@/i18n/utils'; @@ -37,10 +35,6 @@ const featuresHref = t('nav.features.href'); locale={locale} > - - - {t('features.badge')} -

{t('features.title').split(' ').slice(0, -1).join(' ')} {t('features.title').split(' ').slice(-1)[0]}

@@ -48,32 +42,69 @@ const featuresHref = t('nav.features.href');
-
-
-
- {features.map((feature) => { - const slug = feature.id.replace(/\.mdx?$/, ''); - const icon = iconMap[slug] ?? 'check-circle'; - return ( - -
-
-
- -
- -
-

{feature.data.title}

-

{feature.data.description}

-
- {feature.data.tags.map((tag) => ( - {tag} - ))} -
-
-
- ); - })} +
+
+
+

Secure platform, secure data

+

Here at Flowbite we focus on markets where technology, innovation, and capital can unlock long-term value and drive economic growth.

+
+
+
+
+ +
+

Marketing

+

Plan it, create it, launch it. Collaborate seamlessly with all the organization and hit your marketing goals every month with our marketing plan.

+
+
+
+ +
+

Legal

+

Protect your organization, devices and stay compliant with our structured workflows and custom permissions made for you.

+
+
+
+ +
+

Business Automation

+

Auto-assign tasks, send Slack messages, and much more. Now power up with hundreds of new templates to help you get started.

+
+
+
+ +
+

Finance

+

Audit-proof software built for critical financial operations like month-end close and quarterly budgeting.

+
+
+
+ +
+

Enterprise Design

+

Craft beautiful, delightful experiences for both marketing and product with real cross-company collaboration.

+
+
+
+ +
+

Operations

+

Keep your company's lights on with customizable, iterative, and structured workflows built for all efficient teams and individual.

+
+
+
+ +
+

Enterprise Design

+

Craft beautiful, delightful experiences for both marketing and product with real cross-company collaboration.

+
+
+
+ +
+

Operations

+

Keep your company's lights on with customizable, iterative, and structured workflows built for all efficient teams and individual.

+
diff --git a/src/components/landing/HomePage.astro b/src/components/landing/HomePage.astro index 1d714cb..78ee584 100644 --- a/src/components/landing/HomePage.astro +++ b/src/components/landing/HomePage.astro @@ -1,12 +1,10 @@ --- -/** - * Shared home page component — renders in all 4 locales. - */ -import { Hero } from '@/components/hero'; -import Button from '@/components/ui/form/Button/Button.astro'; -import Badge from '@/components/ui/data-display/Badge/Badge.astro'; -import Card from '@/components/ui/data-display/Card/Card.astro'; import Icon from '@/components/ui/primitives/Icon/Icon.astro'; +import { Image } from 'astro:assets'; +import headerImg from '@/assets/header_img.jpg'; +import contentImg from '@/assets/content_image.jpg'; +import armariumImg from '@/assets/armarium_image.jpg'; +import { getCollection } from 'astro:content'; import { useTranslations } from '@/i18n/utils'; import type { Locale } from '@/i18n/ui'; @@ -17,94 +15,210 @@ interface Props { const { locale } = Astro.props; const t = useTranslations(locale); -const features = [ - { key: 'f1', icon: 'layout-dashboard' }, - { key: 'f2', icon: 'list' }, - { key: 'f3', icon: 'pie-chart' }, - { key: 'f4', icon: 'wallet' }, - { key: 'f5', icon: 'target' }, - { key: 'f6', icon: 'shield-check' }, -] as const; +const allPosts = await getCollection('blog', ({ data }) => !data.draft && data.locale === locale); +const posts = allPosts.sort((a, b) => b.data.publishedAt.getTime() - a.data.publishedAt.getTime()).slice(0, 7); +const [featured, ...restPosts] = posts; + +type BlogEntry = { href: string; title: string; description: string }; + +function toEntry(p: (typeof restPosts)[number]): BlogEntry { + return { href: `/blog/${p.id}`, title: p.data.title, description: p.data.description }; +} + +const dummies: BlogEntry[] = [ + { href: '#', title: 'So behältst du den Überblick über deine Finanzen', description: 'Mit einfachen Tricks und der richtigen App kannst du dein Budget im Griff behalten — ohne Stress.' }, + { href: '#', title: '5 Spartipps für den Alltag', description: 'Kleine Änderungen im Alltag können langfristig einen grossen Unterschied machen.' }, + { href: '#', title: 'Warum ein Haushaltsbuch sinnvoll ist', description: 'Wer seine Ausgaben kennt, kann gezielt sparen und Sparziele schneller erreichen.' }, +]; + +function fillTo3(items: (typeof restPosts), offset = 0): BlogEntry[] { + const real = items.map(toEntry); + return [...real, ...dummies].slice(offset, offset + 3); +} + +const colA = fillTo3(restPosts.slice(0, 3)); +const colB = fillTo3(restPosts.slice(3, 6), restPosts.slice(3, 6).length === 0 ? 0 : 0); + --- - - - {t('hero.badge')} - - -

- Armarium Suite —
- Budget & More -

- -

{t('hero.description')}

- - - - - -
- - -
-
-
- - - - - - - - Made in Zürich, Switzerland - - - - {t('trust.privacy')} - - - - {t('trust.free')} - +
+
+
+

+ Armarium Suite
+ Budget & More +

+

+ {t('hero.description')} +

+ + {t('hero.register')} + + +
+
-
+
+ + + + +
+
+
+
+
+
+

+ {t('f1.title' as any)} — {t('f2.title' as any)} +

+

+ {t('hero.description')} +

+
+
+
    + {(['f1','f2','f3'] as const).map((key) => ( +
  • +
    + +
    + {t(`${key}.title` as any)} +
  • + ))} +
+
+ +
- -
-
-
-
- {t('features.badge')} -

- {t('features.title')} -

-

+ + +

+
+ + +
+ + +
+
+

+ {t('features.title')} +

+

+ {t('features.description')} +

+
+
+
    + {(['f1','f2','f3','f4','f5','f6'] as const).map((key) => ( +
  • +
    + +
    + {t(`${key}.title` as any)} +
  • + ))} +
+
+ +
+
+
+
+ + + +
+
+
+

+ {t('nav.blog')} +

+

{t('features.description')}

- -
- {features.map(({ key, icon }) => ( - -
-
- -
-
-

{t(`${key}.title` as any)}

-

{t(`${key}.desc` as any)}

-
-
-
- ))} +
+ + {featured && ( + + )} + +
+ {colA.map((post) => ( + + ))} +
+ +
+ {colB.map((post) => ( + + ))} +
@@ -116,16 +230,13 @@ const features = [ {t('cta.title')}

- {t('cta.desc')} + Kostenlos mitmachen und sofort loslegen.

-
diff --git a/src/components/layout/AppFooter.astro b/src/components/layout/AppFooter.astro new file mode 100644 index 0000000..ff2001f --- /dev/null +++ b/src/components/layout/AppFooter.astro @@ -0,0 +1,58 @@ +--- +import Footer from './Footer.astro'; +import Icon from '@/components/ui/primitives/Icon/Icon.astro'; +import { useTranslations } from '@/i18n/utils'; +import type { Locale } from '@/i18n/ui'; + +interface Props { + locale?: Locale; + background?: 'default' | 'secondary' | 'invert'; +} + +const { locale = 'de', background = 'secondary' } = Astro.props; +const t = useTranslations(locale); +--- + + diff --git a/src/config/nav.config.ts b/src/config/nav.config.ts index 7154c54..78909fe 100644 --- a/src/config/nav.config.ts +++ b/src/config/nav.config.ts @@ -13,7 +13,7 @@ export interface NavItem { export const navItems: NavItem[] = [ { label: 'Blog', href: '/blog', order: 1 }, - { label: 'Features', href: '/projects', order: 2 }, + { label: 'Features', href: '/features', order: 2 }, { label: 'About', href: '/about', order: 3 }, { label: 'Contact', href: '/contact', order: 4 }, ]; diff --git a/src/content/blog/de/budget-tipps.mdx b/src/content/blog/de/budget-tipps.mdx new file mode 100644 index 0000000..b45fe62 --- /dev/null +++ b/src/content/blog/de/budget-tipps.mdx @@ -0,0 +1,32 @@ +--- +title: "5 Tipps für ein besseres Budget" +description: "Mit diesen fünf einfachen Strategien behältst du deine Finanzen im Griff – ohne auf Lebensqualität verzichten zu müssen." +publishedAt: 2026-05-01 +author: "Armarium" +tags: ["budget", "tipps"] +svgSlug: "astro-rocket-features" +featured: false +locale: de +--- + +Ein gutes Budget ist keine Einschränkung – es ist Freiheit. Wer weiss, wohin sein Geld fliesst, kann bewusster entscheiden. + +## 1. Fixkosten zuerst + +Erfasse alle monatlich wiederkehrenden Ausgaben: Miete, Versicherungen, Abonnements. Was übrig bleibt, ist dein frei verfügbares Budget. + +## 2. Die 50/30/20-Regel + +50 % für Notwendigkeiten, 30 % für persönliche Wünsche, 20 % für Sparen. Ein einfaches Prinzip mit grosser Wirkung. + +## 3. Kategorien konsequent nutzen + +Weise jede Ausgabe einer Kategorie zu. So erkennst du schnell, wo du mehr ausgibst als geplant. + +## 4. Wöchentlich überprüfen + +Einmal pro Woche einen kurzen Blick auf die Ausgaben – das reicht, um den Überblick zu behalten. + +## 5. Sparziele setzen + +Ein konkretes Ziel motiviert. Ob Urlaub, Notfallreserve oder neues Gerät – trag es in Armarium ein und verfolge deinen Fortschritt. diff --git a/src/content/blog/de/mehrere-konten.mdx b/src/content/blog/de/mehrere-konten.mdx new file mode 100644 index 0000000..16d7eb3 --- /dev/null +++ b/src/content/blog/de/mehrere-konten.mdx @@ -0,0 +1,24 @@ +--- +title: "Mehrere Konten clever verwalten" +description: "Bankkonto, Kreditkarte, Sparkonto – so behältst du den Überblick über all deine Konten in einer einzigen App." +publishedAt: 2026-04-20 +author: "Armarium" +tags: ["konten", "übersicht"] +svgSlug: "hero-typing-effect" +featured: false +locale: de +--- + +Wer mehrere Konten hat, verliert leicht den Überblick. Armarium bringt alles an einem Ort zusammen. + +## Warum mehrere Konten sinnvoll sind + +Viele Finanzprofis empfehlen getrennte Konten für verschiedene Zwecke: ein Konto für fixe Ausgaben, eines für variable Kosten, eines zum Sparen. + +## Alle Konten in Armarium + +In Armarium legst du beliebig viele Konten an – Bankkonto, Kreditkarte, Bargeld oder digitale Wallets. Alle Transaktionen laufen zentral zusammen. + +## Gesamtbild auf einen Blick + +Das Dashboard zeigt dir jederzeit den Gesamtsaldo über alle Konten – ohne zwischen verschiedenen Apps wechseln zu müssen. diff --git a/src/content/blog/de/sparziele-setzen.mdx b/src/content/blog/de/sparziele-setzen.mdx new file mode 100644 index 0000000..fcc6b81 --- /dev/null +++ b/src/content/blog/de/sparziele-setzen.mdx @@ -0,0 +1,27 @@ +--- +title: "Sparziele richtig setzen und erreichen" +description: "Wie du realistische Sparziele definierst, sie in Armarium verfolgst und Monat für Monat näher ans Ziel kommst." +publishedAt: 2026-04-25 +author: "Armarium" +tags: ["sparziele", "finanzen"] +svgSlug: "design-system-color-tokens" +featured: false +locale: de +--- + +Sparen funktioniert besser mit einem konkreten Ziel. Wer weiss, wofür er spart, bleibt motivierter und gibt weniger unbedacht aus. + +## Was macht ein gutes Sparziel aus? + +Ein gutes Sparziel ist **spezifisch**, **realistisch** und **zeitgebunden**. Statt "ich will mehr sparen" lieber: "Ich spare bis Dezember 2026 CHF 2'000 für einen Urlaub." + +## In Armarium ein Ziel anlegen + +1. Neues Sparziel erstellen +2. Zielbetrag und Deadline festlegen +3. Monatlichen Sparbeitrag definieren +4. Fortschritt verfolgen + +## Kleine Beträge, grosse Wirkung + +Schon CHF 5 täglich ergeben CHF 1'825 im Jahr. Regelmässigkeit schlägt Betragsgrösse. diff --git a/src/content/blog/en/armarium-1-0.mdx b/src/content/blog/en/armarium-1-0.mdx index 25c47ad..c8affb0 100644 --- a/src/content/blog/en/armarium-1-0.mdx +++ b/src/content/blog/en/armarium-1-0.mdx @@ -4,6 +4,7 @@ description: "Dein persönlicher Finanzbegleiter ist live. Budget tracken, Trans publishedAt: 2026-04-13 author: "Armarium" tags: ["launch", "budget", "finanzen", "schweiz"] +svgSlug: "astro-rocket-is-live" featured: true locale: de --- diff --git a/src/content/projects/budget-uebersicht.mdx b/src/content/projects/budget-uebersicht.mdx deleted file mode 100644 index 8a1b68f..0000000 --- a/src/content/projects/budget-uebersicht.mdx +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: "Budget-Übersicht" -description: "Alle Einnahmen und Ausgaben auf einen Blick. Dein aktueller Kontostand immer im Griff – übersichtlich und in Echtzeit." -tags: ["Übersicht", "Dashboard", "Kontostand"] -featured: true -order: 1 ---- - -Die Budget-Übersicht ist das Herzstück von Armarium. Auf einem einzigen Dashboard siehst du deinen aktuellen Kontostand, die Ausgaben und Einnahmen des aktuellen Monats sowie deine wichtigsten Budgetziele. - -## Was du siehst - -- **Kontostand** aller verbundenen Konten in einer Gesamtübersicht -- **Monatliche Bilanz** – wie viel wurde eingenommen, wie viel ausgegeben -- **Budgetfortschritt** – wie weit bist du noch von deinen Limits entfernt -- **Letzte Transaktionen** – die neuesten Buchungen auf einen Blick - -Die Übersicht aktualisiert sich in Echtzeit, sobald du eine neue Transaktion erfasst. diff --git a/src/content/projects/datenschutz-sicherheit.mdx b/src/content/projects/datenschutz-sicherheit.mdx deleted file mode 100644 index 3bab013..0000000 --- a/src/content/projects/datenschutz-sicherheit.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: "Sicher & Privat" -description: "Deine Daten gehören dir. Kein Datenverkauf, kein Tracking – 100% Schweizer Hosting bei Infomaniak, ISO 27001:2022-zertifiziert." -tags: ["Datenschutz", "Schweiz", "ISO 27001"] -featured: true -order: 6 ---- - -Finanzdaten sind sensibel. Armarium behandelt sie entsprechend. - -## Schweizer Hosting - -Alle Daten werden ausschliesslich auf Servern von **Infomaniak** in der Schweiz gespeichert und verarbeitet. Kein Transfer ins Ausland, keine US-Cloud, keine versteckten Datenflüsse. - -Infomaniak ist **ISO 27001:2022-zertifiziert** und trägt das **Swiss Hosting Label**. - -## Was wir nicht tun - -- Kein Verkauf deiner Daten an Dritte -- Kein Tracking oder Werbung -- Keine Weitergabe an Analysedienste - -## Technische Sicherheit - -- Alle Übertragungen verschlüsselt via HTTPS/TLS -- Passwörter gehasht (bcrypt), nie im Klartext gespeichert -- AES-256-Verschlüsselung auf Infrastrukturebene -- Jährliche Penetrationstests durch Infomaniak - -## Rechtliches - -Armarium ist konform mit dem Schweizer **nDSG** (neues Datenschutzgesetz) sowie der europäischen **DSGVO**. diff --git a/src/content/projects/kategorien-berichte.mdx b/src/content/projects/kategorien-berichte.mdx deleted file mode 100644 index 7d1b25d..0000000 --- a/src/content/projects/kategorien-berichte.mdx +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: "Kategorien & Berichte" -description: "Eigene Kategorien definieren und Ausgaben analysieren. Verstehe mit klaren Auswertungen, wohin dein Geld fliesst." -tags: ["Kategorien", "Berichte", "Analyse"] -featured: true -order: 3 ---- - -Kategorien geben deinen Ausgaben eine Struktur. Berichte machen sie sichtbar. - -## Kategorien - -Erstelle Kategorien, die zu deinem Alltag passen – ob Lebensmittel, Mobilität, Freizeit oder Sparen. Jede Transaktion wird einer Kategorie zugewiesen und erscheint automatisch in deinen Auswertungen. - -## Berichte - -- **Monatsübersicht** – Ausgaben nach Kategorie aufgeteilt -- **Vergleich** zwischen verschiedenen Monaten -- **Top-Ausgaben** – wo fliesst am meisten Geld hin? -- **Einnahmen vs. Ausgaben** – Bilanz auf einen Blick - -Die Berichte helfen dir, Muster zu erkennen und bewusster Entscheidungen zu treffen. diff --git a/src/content/projects/mehrere-konten.mdx b/src/content/projects/mehrere-konten.mdx deleted file mode 100644 index ce1022c..0000000 --- a/src/content/projects/mehrere-konten.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: "Mehrere Konten" -description: "Verwalte Bankkonto, Kreditkarte und Bargeld getrennt – alles in einer App zusammengefasst und übersichtlich." -tags: ["Konten", "Kreditkarte", "Bargeld"] -featured: true -order: 4 ---- - -Die meisten Menschen haben mehr als ein Konto. Armarium bildet das ab – einfach und übersichtlich. - -## Unterstützte Kontotypen - -- **Bankkonto** – dein Hauptkonto für Einnahmen und laufende Kosten -- **Kreditkarte** – Ausgaben separat verfolgen, Abrechnung im Überblick -- **Bargeld** – Barzahlungen nicht vergessen -- **Sparkonto** – gezielt Geld zur Seite legen - -## Gesamtübersicht - -Alle Konten werden in der Budget-Übersicht zusammengefasst. Du siehst den Gesamtstand sowie jeden Account einzeln. Transaktionen lassen sich kontoübergreifend filtern und auswerten. diff --git a/src/content/projects/sparziele.mdx b/src/content/projects/sparziele.mdx deleted file mode 100644 index 0cd9495..0000000 --- a/src/content/projects/sparziele.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: "Sparziele" -description: "Setze dir finanzielle Ziele und verfolge deinen Fortschritt – Schritt für Schritt zum Ziel." -tags: ["Sparziele", "Ziele", "Sparen"] -featured: true -order: 5 ---- - -Ob Notgroschen, Urlaub oder neues Fahrrad – Sparziele machen abstrakte Wünsche greifbar. - -## So funktionieren Sparziele - -1. **Ziel definieren** – Name, Zielbetrag und optionales Zieldatum -2. **Fortschritt verfolgen** – wie viel hast du bereits gespart? -3. **Einzahlungen zuweisen** – Transaktionen direkt einem Ziel zuordnen -4. **Ziel erreicht** – Armarium zeigt dir, wann du am Ziel bist - -## Warum Ziele funktionieren - -Wer ein konkretes Ziel vor Augen hat, spart nachweislich mehr. Armarium visualisiert deinen Fortschritt und erinnert dich daran, was du dir vorgenommen hast – ohne störende Benachrichtigungen. diff --git a/src/content/projects/transaktionen.mdx b/src/content/projects/transaktionen.mdx deleted file mode 100644 index a523cf8..0000000 --- a/src/content/projects/transaktionen.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: "Transaktionen erfassen" -description: "Ausgaben und Einnahmen schnell erfassen, kategorisieren und filtern – für lückenlosen Überblick über dein Geldfluss." -tags: ["Transaktionen", "Ausgaben", "Einnahmen"] -featured: true -order: 2 ---- - -Transaktionen sind das Fundament deines Budgets. Armarium macht das Erfassen so einfach wie möglich – damit du es wirklich tust. - -## Wie es funktioniert - -- **Schnelleingabe** für Ausgaben und Einnahmen mit wenigen Klicks -- **Kategorisierung** direkt beim Erfassen – oder nachträglich anpassbar -- **Notizfeld** für zusätzliche Details -- **Datum** frei wählbar – auch rückwirkend eintragen möglich -- **Filterung** nach Zeitraum, Kategorie oder Konto - -Je konsequenter du Transaktionen erfasst, desto aussagekräftiger werden deine Berichte und Auswertungen. diff --git a/src/i18n/ui.ts b/src/i18n/ui.ts index 4f969ec..3449128 100644 --- a/src/i18n/ui.ts +++ b/src/i18n/ui.ts @@ -17,17 +17,13 @@ export const ui = { 'nav.contact': 'Kontakt', // Nav hrefs (locale-aware) 'nav.blog.href': '/blog', - 'nav.features.href': '/projects', + 'nav.features.href': '/features', 'nav.about.href': '/about', 'nav.contact.href': '/contact', // Hero - 'hero.badge': 'Version 1.0 ist da', 'hero.description': 'Behalte den Überblick über deine Finanzen. Erfasse Ausgaben, verwalte Budgets und erreiche deine Sparziele – einfach und übersichtlich.', 'hero.register': 'Registrieren', 'hero.login': 'Login', - // Trust bar - 'trust.privacy': 'Datenschutz garantiert', - 'trust.free': 'Kostenlos starten', // Features section 'features.badge': 'Features', 'features.title': 'Alles was du brauchst', @@ -45,15 +41,32 @@ export const ui = { 'f5.desc': 'Setze dir finanzielle Ziele und verfolge deinen Fortschritt – Schritt für Schritt zum Ziel.', 'f6.title': 'Sicher & Privat', 'f6.desc': 'Deine Daten gehören dir. Kein Datenverkauf, kein Tracking – volle Kontrolle über deine Finanzdaten.', + // Blog section + 'blog.section.title': 'Neuigkeiten & Updates', + 'blog.readmore': 'Weiterlesen', + 'blog.allposts': 'Alle Beiträge', + // Why Armarium section + 'why.title': 'Finanzmanagement neu gedacht', + 'why.intro': 'Armarium vereinfacht dein Finanzleben – egal ob du Ausgaben verfolgst, Budgets planst oder Sparziele setzt.', + 'why.item1.title': 'Daten in der Schweiz', + 'why.item1.desc': 'Deine Finanzdaten werden ausschliesslich auf Schweizer Servern gespeichert. Kein Datenverkauf, kein Tracking – volle Kontrolle bleibt bei dir.', + 'why.item2.title': 'Clevere Budgetverwaltung', + 'why.item2.desc': 'Behalte alle Einnahmen und Ausgaben im Blick. Automatische Kategorisierung und übersichtliche Grafiken zeigen dir genau, wo dein Geld hinfliesst.', + 'why.item3.title': 'Individuell anpassbar', + 'why.item3.desc': 'Erstelle eigene Kategorien, verwalte mehrere Konten und passe die App genau an deinen Alltag an.', + 'why.item4.title': 'Mehrere Konten', + 'why.item4.desc': 'Verwalte Bankkonto, Kreditkarte und Bargeld getrennt – alles übersichtlich in einer einzigen App.', + 'why.learnmore': 'Mehr erfahren', + 'why.footer': 'Kostenlos starten – keine Kreditkarte erforderlich.', // CTA 'cta.title': 'Bereit, dein Budget im Griff zu haben?', 'cta.desc': 'Kostenlos registrieren und sofort loslegen. Keine Kreditkarte erforderlich.', 'cta.register': 'Kostenlos registrieren', 'cta.login': 'Bereits registriert? Login', // Footer - 'footer.tagline': 'Dein persönlicher Finanzbegleiter – Budget im Blick, Ziele im Fokus. 🇨🇭 Made in Zürich, Switzerland.', - 'footer.copyright': '© {year} Armarium. Alle Rechte vorbehalten.', - 'footer.app': 'App', + 'footer.tagline': 'Dein persönlicher Finanzbegleiter – Budget im Blick, Ziele im Fokus.', + 'footer.copyright': '© {year} Armarium Suite', + 'footer.app': 'Produkt', 'footer.start': 'Jetzt starten', 'footer.register': 'Registrieren', 'footer.legal': 'Rechtliches', @@ -89,6 +102,20 @@ export const ui = { 'about.cta.title': 'Bereit loszulegen?', 'about.cta.desc': 'Kostenlos registrieren und Armarium sofort nutzen.', 'about.cta.back': 'Zurück zur Startseite', + 'about.team.title': 'Das Team hinter Armarium', + 'about.team.desc1': 'Armarium Suite ist ein Ein-Mann-Projekt, das aus einem echten persönlichen Bedürfnis entstanden ist: eine einfache, datenschutzfreundliche App zur Budgetverwaltung zu haben – ohne Kompromisse.', + 'about.team.desc2': 'Als Entwickler und Nutzer in einem stecke ich mein ganzes Herzblut in die App. Jede Funktion ist bewusst gewählt, jede Entscheidung zielt auf Einfachheit und Vertrauen.', + 'about.founder.role': 'Founder', + 'about.founder.bio': 'Ich habe Armarium Suite gegründet, weil ich selbst eine einfache, datenschutzfreundliche App zur Budgetverwaltung gesucht habe — und keine gefunden habe, die wirklich überzeugt. Armarium ist meine Antwort darauf: klar, lokal und ohne Kompromisse beim Datenschutz.', + 'about.faq.title': 'Häufig gestellte Fragen', + 'about.faq.q1': 'Ist Armarium Suite kostenlos?', + 'about.faq.a1': 'Ja, Armarium Suite ist vollständig kostenlos nutzbar. Es gibt keine versteckten Kosten, keine Abonnements und keine Premium-Funktionen hinter einer Paywall.', + 'about.faq.q2': 'Wo werden meine Daten gespeichert?', + 'about.faq.a2': 'Deine Finanzdaten werden ausschliesslich lokal in deinem Browser gespeichert. Wir haben keinen Zugriff auf deine Transaktionen, Budgets oder Sparziele. Deine Daten verlassen dein Gerät nicht.', + 'about.faq.q3': 'Funktioniert Armarium auf meinem Gerät?', + 'about.faq.a3': 'Armarium Suite ist eine Web-App und läuft in jedem modernen Browser – auf Desktop, Tablet und Smartphone. Du kannst sie auch als PWA auf deinem Startbildschirm installieren.', + 'about.faq.q4': 'Kann ich meine Daten exportieren?', + 'about.faq.a4': 'Ja, du kannst alle deine Daten jederzeit als CSV oder JSON exportieren. Gehe dazu unter Einstellungen → Daten exportieren.', // Contact page 'contact.badge': 'Kontakt', 'contact.title': 'Schreib uns.', @@ -125,12 +152,9 @@ export const ui = { 'nav.features.href': '/fr/features', 'nav.about.href': '/fr/about', 'nav.contact.href': '/fr/contact', - 'hero.badge': 'Version 1.0 disponible', 'hero.description': 'Gardez le contrôle de vos finances. Enregistrez vos dépenses, gérez vos budgets et atteignez vos objectifs d\'épargne – simplement et clairement.', 'hero.register': 'S\'inscrire', 'hero.login': 'Connexion', - 'trust.privacy': 'Protection des données garantie', - 'trust.free': 'Commencer gratuitement', 'features.badge': 'Fonctionnalités', 'features.title': 'Tout ce qu\'il vous faut', 'features.description': 'Armarium réunit toutes les fonctions essentielles pour une gestion financière solide dans une application claire.', @@ -146,13 +170,28 @@ export const ui = { 'f5.desc': 'Fixez-vous des objectifs financiers et suivez votre progression – pas à pas vers le but.', 'f6.title': 'Sûr & privé', 'f6.desc': 'Vos données vous appartiennent. Pas de vente, pas de tracking – contrôle total sur vos données financières.', + 'blog.section.title': 'Actualités & mises à jour', + 'blog.readmore': 'Lire la suite', + 'blog.allposts': 'Tous les articles', + 'why.title': 'Repensez votre gestion financière', + 'why.intro': 'Armarium simplifie votre vie financière – que vous suiviez des dépenses, planifiiez des budgets ou fixiez des objectifs d\'épargne.', + 'why.item1.title': 'Données en Suisse', + 'why.item1.desc': 'Vos données financières sont stockées exclusivement sur des serveurs suisses. Pas de vente de données, pas de tracking – vous gardez le contrôle.', + 'why.item2.title': 'Gestion budgétaire intelligente', + 'why.item2.desc': 'Gardez une vue d\'ensemble sur vos revenus et dépenses. La catégorisation automatique et les graphiques clairs montrent exactement où va votre argent.', + 'why.item3.title': 'Entièrement personnalisable', + 'why.item3.desc': 'Créez vos propres catégories, gérez plusieurs comptes et adaptez l\'app à votre quotidien.', + 'why.item4.title': 'Plusieurs comptes', + 'why.item4.desc': 'Gérez compte bancaire, carte de crédit et espèces séparément – tout regroupé dans une seule app.', + 'why.learnmore': 'En savoir plus', + 'why.footer': 'Commencer gratuitement – aucune carte de crédit requise.', 'cta.title': 'Prêt à maîtriser votre budget?', 'cta.desc': 'Inscrivez-vous gratuitement et commencez immédiatement. Aucune carte de crédit requise.', 'cta.register': 'S\'inscrire gratuitement', 'cta.login': 'Déjà inscrit? Connexion', - 'footer.tagline': 'Votre assistant financier personnel – budget maîtrisé, objectifs en vue. 🇨🇭 Made in Zürich, Switzerland.', - 'footer.copyright': '© {year} Armarium. Tous droits réservés.', - 'footer.app': 'App', + 'footer.tagline': 'Votre assistant financier personnel – budget maîtrisé, objectifs en vue.', + 'footer.copyright': '© {year} Armarium Suite', + 'footer.app': 'Produit', 'footer.start': 'Commencer', 'footer.register': 'S\'inscrire', 'footer.legal': 'Légal', @@ -187,6 +226,20 @@ export const ui = { 'about.cta.title': 'Prêt à commencer?', 'about.cta.desc': 'Inscrivez-vous gratuitement et utilisez Armarium immédiatement.', 'about.cta.back': 'Retour à l\'accueil', + 'about.team.title': 'L\'équipe derrière Armarium', + 'about.team.desc1': 'Armarium Suite est un projet solo né d\'un besoin personnel réel : disposer d\'une app de gestion budgétaire simple et respectueuse de la vie privée – sans compromis.', + 'about.team.desc2': 'En tant que développeur et utilisateur à la fois, je mets tout mon cœur dans l\'app. Chaque fonctionnalité est choisie délibérément, chaque décision vise la simplicité et la confiance.', + 'about.founder.role': 'Founder', + 'about.founder.bio': 'J\'ai fondé Armarium Suite parce que je cherchais moi-même une app simple et respectueuse de la vie privée pour gérer mon budget — et je n\'en ai pas trouvé qui soit vraiment convaincante. Armarium est ma réponse : claire, locale et sans compromis sur la confidentialité.', + 'about.faq.title': 'Questions fréquentes', + 'about.faq.q1': 'Armarium Suite est-il gratuit ?', + 'about.faq.a1': 'Oui, Armarium Suite est entièrement gratuit. Pas de frais cachés, pas d\'abonnement, pas de fonctionnalités premium derrière un paywall.', + 'about.faq.q2': 'Où sont stockées mes données ?', + 'about.faq.a2': 'Vos données financières sont stockées uniquement en local dans votre navigateur. Nous n\'avons pas accès à vos transactions, budgets ou objectifs d\'épargne. Vos données ne quittent pas votre appareil.', + 'about.faq.q3': 'Armarium fonctionne-t-il sur mon appareil ?', + 'about.faq.a3': 'Armarium Suite est une web app qui fonctionne dans tout navigateur moderne – sur desktop, tablette et smartphone. Vous pouvez aussi l\'installer comme PWA sur votre écran d\'accueil.', + 'about.faq.q4': 'Puis-je exporter mes données ?', + 'about.faq.a4': 'Oui, vous pouvez exporter toutes vos données à tout moment en CSV ou JSON. Allez dans Paramètres → Exporter les données.', 'contact.badge': 'Contact', 'contact.title': 'Écrivez-nous.', 'contact.desc': 'Utilisez le formulaire ou contactez-nous directement. Nous répondons dans un jour ouvrable.', @@ -220,12 +273,9 @@ export const ui = { 'nav.features.href': '/it/features', 'nav.about.href': '/it/about', 'nav.contact.href': '/it/contact', - 'hero.badge': 'Versione 1.0 disponibile', 'hero.description': 'Tieni sotto controllo le tue finanze. Registra le spese, gestisci i budget e raggiungi i tuoi obiettivi di risparmio – in modo semplice e chiaro.', 'hero.register': 'Registrarsi', 'hero.login': 'Accedi', - 'trust.privacy': 'Privacy garantita', - 'trust.free': 'Inizia gratuitamente', 'features.badge': 'Funzionalità', 'features.title': 'Tutto ciò di cui hai bisogno', 'features.description': 'Armarium riunisce tutte le funzioni essenziali per una gestione finanziaria solida in un\'app chiara.', @@ -241,13 +291,28 @@ export const ui = { 'f5.desc': 'Fissa obiettivi finanziari e monitora i tuoi progressi – passo dopo passo verso il traguardo.', 'f6.title': 'Sicuro & privato', 'f6.desc': 'I tuoi dati sono tuoi. Nessuna vendita, nessun tracking – pieno controllo sui tuoi dati finanziari.', + 'blog.section.title': 'Novità & aggiornamenti', + 'blog.readmore': 'Leggi di più', + 'blog.allposts': 'Tutti gli articoli', + 'why.title': 'Ripensa la tua gestione finanziaria', + 'why.intro': 'Armarium semplifica la tua vita finanziaria – che tu voglia tracciare spese, pianificare budget o fissare obiettivi di risparmio.', + 'why.item1.title': 'Dati in Svizzera', + 'why.item1.desc': 'I tuoi dati finanziari sono archiviati esclusivamente su server svizzeri. Nessuna vendita di dati, nessun tracking – il controllo rimane tuo.', + 'why.item2.title': 'Gestione intelligente del budget', + 'why.item2.desc': 'Tieni d\'occhio tutte le entrate e le uscite. La categorizzazione automatica e i grafici chiari mostrano esattamente dove va il tuo denaro.', + 'why.item3.title': 'Completamente personalizzabile', + 'why.item3.desc': 'Crea categorie personalizzate, gestisci più conti e adatta l\'app alla tua vita quotidiana.', + 'why.item4.title': 'Più conti', + 'why.item4.desc': 'Gestisci conto bancario, carta di credito e contanti separatamente – tutto in un\'unica app.', + 'why.learnmore': 'Scopri di più', + 'why.footer': 'Inizia gratuitamente – nessuna carta di credito richiesta.', 'cta.title': 'Pronto a gestire il tuo budget?', 'cta.desc': 'Registrati gratuitamente e inizia subito. Nessuna carta di credito richiesta.', 'cta.register': 'Registrarsi gratuitamente', 'cta.login': 'Già registrato? Accedi', - 'footer.tagline': 'Il tuo assistente finanziario personale – budget sotto controllo, obiettivi in vista. 🇨🇭 Made in Zürich, Switzerland.', - 'footer.copyright': '© {year} Armarium. Tutti i diritti riservati.', - 'footer.app': 'App', + 'footer.tagline': 'Il tuo assistente finanziario personale – budget sotto controllo, obiettivi in vista.', + 'footer.copyright': '© {year} Armarium Suite', + 'footer.app': 'Prodotto', 'footer.start': 'Inizia', 'footer.register': 'Registrarsi', 'footer.legal': 'Legale', @@ -282,6 +347,20 @@ export const ui = { 'about.cta.title': 'Pronto per iniziare?', 'about.cta.desc': 'Registrati gratuitamente e usa Armarium subito.', 'about.cta.back': 'Torna alla home', + 'about.team.title': 'Il team dietro Armarium', + 'about.team.desc1': 'Armarium Suite è un progetto individuale nato da un bisogno personale reale: avere un\'app semplice e rispettosa della privacy per gestire il budget – senza compromessi.', + 'about.team.desc2': 'Come sviluppatore e utente allo stesso tempo, metto tutto il mio impegno nell\'app. Ogni funzionalità è scelta deliberatamente, ogni decisione punta alla semplicità e alla fiducia.', + 'about.founder.role': 'Founder', + 'about.founder.bio': 'Ho fondato Armarium Suite perché cercavo io stesso un\'app semplice e rispettosa della privacy per gestire il budget — e non ne ho trovata una davvero convincente. Armarium è la mia risposta: chiara, locale e senza compromessi sulla privacy.', + 'about.faq.title': 'Domande frequenti', + 'about.faq.q1': 'Armarium Suite è gratuito?', + 'about.faq.a1': 'Sì, Armarium Suite è completamente gratuito. Nessun costo nascosto, nessun abbonamento, nessuna funzionalità premium a pagamento.', + 'about.faq.q2': 'Dove vengono archiviati i miei dati?', + 'about.faq.a2': 'I tuoi dati finanziari vengono archiviati esclusivamente in locale nel tuo browser. Non abbiamo accesso alle tue transazioni, budget o obiettivi di risparmio. I tuoi dati non lasciano il tuo dispositivo.', + 'about.faq.q3': 'Armarium funziona sul mio dispositivo?', + 'about.faq.a3': 'Armarium Suite è una web app che funziona in qualsiasi browser moderno – su desktop, tablet e smartphone. Puoi anche installarla come PWA sulla schermata iniziale.', + 'about.faq.q4': 'Posso esportare i miei dati?', + 'about.faq.a4': 'Sì, puoi esportare tutti i tuoi dati in qualsiasi momento come CSV o JSON. Vai su Impostazioni → Esporta dati.', 'contact.badge': 'Contatto', 'contact.title': 'Scrivici.', 'contact.desc': 'Usa il modulo o contattaci direttamente. Rispondiamo entro un giorno lavorativo.', @@ -315,12 +394,9 @@ export const ui = { 'nav.features.href': '/en/features', 'nav.about.href': '/en/about', 'nav.contact.href': '/en/contact', - 'hero.badge': 'Version 1.0 is here', 'hero.description': 'Keep track of your finances. Record expenses, manage budgets and reach your savings goals – simply and clearly.', 'hero.register': 'Sign up', 'hero.login': 'Login', - 'trust.privacy': 'Privacy guaranteed', - 'trust.free': 'Start for free', 'features.badge': 'Features', 'features.title': 'Everything you need', 'features.description': 'Armarium brings together all the essential functions for solid financial management in one clear app.', @@ -336,13 +412,28 @@ export const ui = { 'f5.desc': 'Set financial goals and track your progress – step by step towards the target.', 'f6.title': 'Secure & Private', 'f6.desc': 'Your data belongs to you. No data selling, no tracking – full control over your financial data.', + 'blog.section.title': 'News & updates', + 'blog.readmore': 'Read more', + 'blog.allposts': 'All posts', + 'why.title': 'Financial management reimagined', + 'why.intro': 'Armarium simplifies your financial life – whether you\'re tracking expenses, planning budgets, or setting savings goals.', + 'why.item1.title': 'Data stored in Switzerland', + 'why.item1.desc': 'Your financial data is stored exclusively on Swiss servers. No data selling, no tracking – full control stays with you.', + 'why.item2.title': 'Smart budget management', + 'why.item2.desc': 'Keep track of all income and expenses. Automatic categorisation and clear charts show you exactly where your money goes.', + 'why.item3.title': 'Fully customisable', + 'why.item3.desc': 'Create your own categories, manage multiple accounts and tailor the app to your everyday life.', + 'why.item4.title': 'Multiple Accounts', + 'why.item4.desc': 'Manage bank account, credit card and cash separately – all combined in one app.', + 'why.learnmore': 'Learn more', + 'why.footer': 'Start for free – no credit card required.', 'cta.title': 'Ready to take control of your budget?', 'cta.desc': 'Sign up for free and get started immediately. No credit card required.', 'cta.register': 'Sign up for free', 'cta.login': 'Already registered? Login', - 'footer.tagline': 'Your personal finance companion – budget in check, goals in focus. 🇨🇭 Made in Zürich, Switzerland.', - 'footer.copyright': '© {year} Armarium. All rights reserved.', - 'footer.app': 'App', + 'footer.tagline': 'Your personal finance companion – budget in check, goals in focus.', + 'footer.copyright': '© {year} Armarium Suite', + 'footer.app': 'Product', 'footer.start': 'Get started', 'footer.register': 'Sign up', 'footer.legal': 'Legal', @@ -377,6 +468,20 @@ export const ui = { 'about.cta.title': 'Ready to get started?', 'about.cta.desc': 'Sign up for free and start using Armarium right away.', 'about.cta.back': 'Back to home', + 'about.team.title': 'The team behind Armarium', + 'about.team.desc1': 'Armarium Suite is a solo project born from a real personal need: having a simple, privacy-friendly app for budget management – without compromise.', + 'about.team.desc2': 'As both developer and user, I put my heart into the app. Every feature is deliberately chosen, every decision aimed at simplicity and trust.', + 'about.founder.role': 'Founder', + 'about.founder.bio': 'I founded Armarium Suite because I was looking for a simple, privacy-friendly app to manage my budget — and couldn\'t find one that truly convinced me. Armarium is my answer: clear, local and uncompromising on privacy.', + 'about.faq.title': 'Frequently asked questions', + 'about.faq.q1': 'Is Armarium Suite free?', + 'about.faq.a1': 'Yes, Armarium Suite is completely free. No hidden costs, no subscriptions, no premium features behind a paywall.', + 'about.faq.q2': 'Where is my data stored?', + 'about.faq.a2': 'Your financial data is stored exclusively locally in your browser. We have no access to your transactions, budgets or savings goals. Your data never leaves your device.', + 'about.faq.q3': 'Does Armarium work on my device?', + 'about.faq.a3': 'Armarium Suite is a web app that works in any modern browser – on desktop, tablet and smartphone. You can also install it as a PWA on your home screen.', + 'about.faq.q4': 'Can I export my data?', + 'about.faq.a4': 'Yes, you can export all your data at any time as CSV or JSON. Go to Settings → Export data.', 'contact.badge': 'Contact', 'contact.title': 'Write to us.', 'contact.desc': 'Use the form or contact us directly. We respond within one business day.', diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 31002e3..0acf69b 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -88,6 +88,21 @@ if (includeProfessionalServiceSchema) { + + +