Resources tuneup
This commit is contained in:
@@ -0,0 +1,716 @@
|
||||
# Officer.dev Marketing Website Plan
|
||||
|
||||
> Written by Claude for Claude. This document covers the full marketing website — structure, copy, visuals, and demo video plans. When resuming, read this first and walk the user through the strategy before building.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Positioning & Messaging Strategy](#1-positioning--messaging-strategy)
|
||||
2. [Site Map](#2-site-map)
|
||||
3. [Page-by-Page Breakdown](#3-page-by-page-breakdown)
|
||||
4. [Copy Bank](#4-copy-bank)
|
||||
5. [Visual Identity for Marketing](#5-visual-identity-for-marketing)
|
||||
6. [Demo Videos Plan](#6-demo-videos-plan)
|
||||
7. [Technical Implementation](#7-technical-implementation)
|
||||
8. [Launch Considerations](#8-launch-considerations)
|
||||
|
||||
---
|
||||
|
||||
## 1. Positioning & Messaging Strategy
|
||||
|
||||
### The Core Idea
|
||||
|
||||
Officer is not a developer tool. It's not an AI chatbot wrapper. It's an **operating system** — a central place where AI does your repetitive work so you can do what matters.
|
||||
|
||||
### Positioning Triangle
|
||||
|
||||
```
|
||||
OFFICER
|
||||
/ \
|
||||
Easier More Powerful
|
||||
than than
|
||||
| |
|
||||
OpenClaw Claude Work
|
||||
(open source (polished but
|
||||
but complex) locked down)
|
||||
```
|
||||
|
||||
**vs. OpenClaw/Open Source AI tools**: "You shouldn't need a CS degree to use AI. Officer gives you the same power — with a UI your team actually wants to use."
|
||||
|
||||
**vs. Claude Work/Enterprise AI**: "Enterprise AI is a walled garden. Officer is open source, self-hosted, and yours. No data leaves your servers unless you say so."
|
||||
|
||||
**vs. Building it yourself**: "You could stitch together 15 tools and spend months on glue code. Or you could install Officer in five minutes."
|
||||
|
||||
### Messaging Pillars
|
||||
|
||||
| Pillar | For Individuals | For Companies |
|
||||
|--------|----------------|---------------|
|
||||
| **Automation** | "Automate your life. Have more time to live it." | "Every minute your team spends on repetitive work is a minute wasted." |
|
||||
| **AI-Native** | "An AI that doesn't just chat — it acts." | "Give every employee an AI-powered workspace." |
|
||||
| **Self-Hosted** | "Your data, your server, your rules." | "Enterprise-grade AI without enterprise-grade surveillance." |
|
||||
| **Open Source** | "Built in the open. Extend it however you want." | "No vendor lock-in. No surprise pricing changes." |
|
||||
|
||||
### Tagline Options
|
||||
|
||||
**Primary (hero):**
|
||||
> **Your AI-powered operating system — everywhere.**
|
||||
|
||||
**Alternatives to test:**
|
||||
> **Stop managing. Start living.**
|
||||
>
|
||||
> **The last tool you'll need.**
|
||||
>
|
||||
> **One platform. Everything automated.**
|
||||
|
||||
**For the business/enterprise angle:**
|
||||
> **What if your entire company ran itself?**
|
||||
>
|
||||
> **The company intranet that actually works.**
|
||||
>
|
||||
> **Fortunes are lost to repetitive work every day. Not anymore.**
|
||||
|
||||
### Tone of Voice
|
||||
|
||||
- **Confident but not arrogant** — we know what we are, we don't trash competitors
|
||||
- **Clear and direct** — no jargon, no buzzword soup
|
||||
- **Warm** — the duck mascot sets the tone. Serious product, friendly personality
|
||||
- **Action-oriented** — every section should make you want to try it
|
||||
|
||||
---
|
||||
|
||||
## 2. Site Map
|
||||
|
||||
```
|
||||
officer.dev/
|
||||
├── / (Landing / Home)
|
||||
├── /features
|
||||
│ ├── /features/ai-assistant
|
||||
│ ├── /features/file-management
|
||||
│ ├── /features/automation
|
||||
│ └── /features/workspaces
|
||||
├── /pricing
|
||||
├── /docs (external link to docs site)
|
||||
├── /marketplace (coming soon / waitlist)
|
||||
├── /enterprise
|
||||
├── /open-source
|
||||
├── /blog (future)
|
||||
└── /about
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Page-by-Page Breakdown
|
||||
|
||||
### 3.1 Landing Page (Home)
|
||||
|
||||
The landing page is the entire pitch in one scroll. It must convert three different audiences: individual users, small teams, and enterprises.
|
||||
|
||||
#### Section 1: Hero
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ [Nav: Logo | Features | Pricing | Docs | GitHub]│
|
||||
│ [ Star on GitHub | Login]│
|
||||
│ │
|
||||
│ Your AI-powered operating │
|
||||
│ system — everywhere. │
|
||||
│ │
|
||||
│ Open source. Self-hosted. Free forever. │
|
||||
│ │
|
||||
│ [ Get Started — Free ] [ Watch Demo ▶ ] │
|
||||
│ │
|
||||
│ 🦆 (animated duck walks across) │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ (Hero product screenshot/video) │ │
|
||||
│ │ Dashboard with widgets + chat open │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Trusted by developers at [logos if available] │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Copy:**
|
||||
- Headline: "Your AI-powered operating system — everywhere."
|
||||
- Subheadline: "Open source. Self-hosted. Free forever."
|
||||
- CTA Primary: "Get Started — Free"
|
||||
- CTA Secondary: "Watch Demo"
|
||||
- Background: landscape1.png with gradient overlay
|
||||
|
||||
**Behavior:**
|
||||
- Duck walks across the hero from right to left (CSS/JS animation, lightweight — not the 3D model)
|
||||
- Product screenshot below the fold, slightly overlapping
|
||||
- Subtle parallax on scroll
|
||||
- GitHub stars badge updates live
|
||||
|
||||
#### Section 2: The Problem
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ Every day, you... │
|
||||
│ │
|
||||
│ ┌────────┐ ┌────────┐ ┌────────┐ │
|
||||
│ │ Rename │ │ Organize│ │ Copy │ │
|
||||
│ │ 47 │ │ files │ │ data │ │
|
||||
│ │ files │ │ into │ │ between│ │
|
||||
│ │ │ │ folders │ │ apps │ │
|
||||
│ └────────┘ └────────┘ └────────┘ │
|
||||
│ │
|
||||
│ ┌────────┐ ┌────────┐ ┌────────┐ │
|
||||
│ │ Format │ │ Convert │ │ Search │ │
|
||||
│ │ reports│ │ formats │ │ through│ │
|
||||
│ │ │ │ │ │ docs │ │
|
||||
│ └────────┘ └────────┘ └────────┘ │
|
||||
│ │
|
||||
│ This isn't work. It's busywork. │
|
||||
│ And it costs more than you think. │
|
||||
│ │
|
||||
│ [$X,XXX per employee per year wasted] │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Copy:**
|
||||
- "Every day, you rename files. Organize folders. Copy data between apps. Format reports. Convert formats. Search through documents."
|
||||
- "This isn't work. It's busywork."
|
||||
- "And it's costing you more than you think."
|
||||
- Animated counter or stat: estimated cost of repetitive work per employee/year
|
||||
|
||||
#### Section 3: The Solution (Feature Overview)
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ Meet Officer. │
|
||||
│ │
|
||||
│ The platform that combines AI, file management, │
|
||||
│ automation, and workspaces into one self-hosted │
|
||||
│ operating system. │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ (Animated product showcase) │ │
|
||||
│ │ Cycling through: Chat → Files → │ │
|
||||
│ │ Automation → Dashboard │ │
|
||||
│ │ │ │
|
||||
│ └─────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
|
||||
│ │ 🤖 │ │ 📁 │ │ ⚡ │ │ 🏠 │ │
|
||||
│ │ AI │ │Files │ │Auto- │ │Work- │ │
|
||||
│ │Assist│ │ │ │mate │ │space │ │
|
||||
│ └──────┘ └──────┘ └──────┘ └──────┘ │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Four feature cards:**
|
||||
|
||||
1. **AI Assistant** — "Not just chat. An AI that reads your files, runs your tasks, and gets things done."
|
||||
2. **File Management** — "Your entire digital life in one place. Browse, preview, edit, convert, transcribe."
|
||||
3. **Automation** — "Build workflows that run themselves. Tasks, cron jobs, pipelines — without writing code."
|
||||
4. **Workspaces** — "Your desk, digitized. Combine any tool into a custom layout that fits how you work."
|
||||
|
||||
Each card links to its feature detail page.
|
||||
|
||||
#### Section 4: For You / For Your Team (Split Section)
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ ┌─────────────────┐ ┌─────────────────────┐ │
|
||||
│ │ │ │ │ │
|
||||
│ │ FOR YOU │ │ FOR YOUR COMPANY │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ "Automate your │ │ "What if your │ │
|
||||
│ │ life. Have more │ │ entire team had an │ │
|
||||
│ │ time to live │ │ AI-powered intranet │ │
|
||||
│ │ it." │ │ that actually │ │
|
||||
│ │ │ │ worked?" │ │
|
||||
│ │ • Personal AI │ │ │ │
|
||||
│ │ assistant │ │ • Role-based access │ │
|
||||
│ │ • File organiz- │ │ • Shared workspaces │ │
|
||||
│ │ ation on │ │ • Company-wide │ │
|
||||
│ │ autopilot │ │ automation │ │
|
||||
│ │ • Smart dash- │ │ • Self-hosted: │ │
|
||||
│ │ board with │ │ your data stays │ │
|
||||
│ │ your goals │ │ on your servers │ │
|
||||
│ │ • Voice notes, │ │ • Plugin ecosystem │ │
|
||||
│ │ OCR, TTS │ │ for custom needs │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ [Try Free →] │ │ [Enterprise →] │ │
|
||||
│ │ │ │ │ │
|
||||
│ └─────────────────┘ └─────────────────────┘ │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### Section 5: How It Works
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ Up and running in 5 minutes. │
|
||||
│ │
|
||||
│ 1. Install │
|
||||
│ ┌──────────────────────────────────┐ │
|
||||
│ │ $ curl -fsSL install.officer.dev │ │
|
||||
│ │ | sh │ │
|
||||
│ └──────────────────────────────────┘ │
|
||||
│ One command. That's it. │
|
||||
│ │
|
||||
│ 2. Open your browser │
|
||||
│ Navigate to localhost:5000. │
|
||||
│ Create your admin account. │
|
||||
│ │
|
||||
│ 3. Start automating │
|
||||
│ Your AI assistant is ready. │
|
||||
│ Your files are connected. │
|
||||
│ Your first automation is one click away. │
|
||||
│ │
|
||||
│ [Get Started — Free] │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### Section 6: Open Source & Community
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ Built in the open. Extended by everyone. │
|
||||
│ │
|
||||
│ Officer is open source under [LICENSE]. │
|
||||
│ Read every line. Modify anything. │
|
||||
│ Self-host for free, forever. │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ ⭐ │ │ 🔌 │ │ 🎨 │ │
|
||||
│ │ [count] │ │ Plugins │ │ Themes │ │
|
||||
│ │ GitHub │ │ Build & │ │ Make it │ │
|
||||
│ │ Stars │ │ share │ │ yours │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ │
|
||||
│ │
|
||||
│ Marketplace coming soon. │
|
||||
│ Build plugins. Sell themes. Earn money. │
|
||||
│ │
|
||||
│ [Star on GitHub ⭐] [Join the community] │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### Section 7: Pricing Preview
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ Simple pricing. No surprises. │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌───────────┐ ┌──────────┐ │
|
||||
│ │ Self- │ │ Cloud │ │ Enter- │ │
|
||||
│ │ Hosted │ │ │ │ prise │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ FREE │ │ $XX/mo │ │ Custom │ │
|
||||
│ │ forever │ │ per user │ │ │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ Full │ │ Everything│ │ SLA, │ │
|
||||
│ │ features │ │ hosted & │ │ support, │ │
|
||||
│ │ Your │ │ managed │ │ custom │ │
|
||||
│ │ servers │ │ for you │ │ features │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ [Install]│ │ [Start] │ │ [Talk] │ │
|
||||
│ └──────────┘ └───────────┘ └──────────┘ │
|
||||
│ │
|
||||
│ All plans include all features. │
|
||||
│ The only difference is who runs the server. │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Key messaging**: "All plans include all features. The only difference is who runs the server." This is a powerful differentiator. No feature gating.
|
||||
|
||||
#### Section 8: CTA / Footer
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ Ready to stop wasting time? │
|
||||
│ │
|
||||
│ [Get Started — Free] [Book a Demo] │
|
||||
│ │
|
||||
│ ───────────────────────────────────────────── │
|
||||
│ │
|
||||
│ officer.dev │
|
||||
│ Product: Features | Pricing | Docs │
|
||||
│ Community: GitHub | Discord | Blog │
|
||||
│ Company: About | Enterprise | Contact │
|
||||
│ │
|
||||
│ © 2026 Officer.dev │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3.2 Features Page (`/features`)
|
||||
|
||||
Overview page with anchor-linked sections for each feature area. Each section has:
|
||||
- Feature title & one-line pitch
|
||||
- 3-4 bullet capabilities
|
||||
- Embedded demo video or animated screenshot
|
||||
- CTA to try it
|
||||
|
||||
**Feature areas:**
|
||||
|
||||
#### AI Assistant (`/features/ai-assistant`)
|
||||
- Multi-provider (Claude, OpenCode, Pi-Mono)
|
||||
- File-aware — reads, edits, and creates files
|
||||
- Task-aware — runs automation on your behalf
|
||||
- Voice input, image analysis, code understanding
|
||||
- Session persistence across devices
|
||||
|
||||
**Demo video**: Show a conversation where the user asks "organize my downloads folder by file type" and the AI does it, showing the file browser updating in real-time.
|
||||
|
||||
#### File Management (`/features/file-management`)
|
||||
- Browse, upload, download, search
|
||||
- Built-in viewers: text, images, PDFs, audio, video
|
||||
- AI-powered: OCR, text-to-speech, transcription, audio extraction
|
||||
- Video transcoding for any format
|
||||
- Archive extraction (zip, tar, 7z, rar)
|
||||
- Git clone, yt-dlp download integration
|
||||
|
||||
**Demo video**: Upload a photo of a receipt → OCR extracts the text → AI categorizes the expense. All in Officer.
|
||||
|
||||
#### Automation (`/features/automation`)
|
||||
- Tasks triggered by file type, schedule, or manually
|
||||
- Workflows chaining multiple steps
|
||||
- Cron jobs for recurring work
|
||||
- Background processes
|
||||
- Skills system — teach AI new capabilities
|
||||
|
||||
**Demo video**: Show setting up a task that compresses images when they're uploaded to a specific folder.
|
||||
|
||||
#### Workspaces (`/features/workspaces`)
|
||||
- Multi-panel layouts
|
||||
- Combine chat + files + any tool
|
||||
- Save and switch between workspace configurations
|
||||
- Create workspace templates for team
|
||||
|
||||
**Demo video**: Building a "Content Creation" workspace with file browser on the left, AI chat in the middle, and preview on the right.
|
||||
|
||||
---
|
||||
|
||||
### 3.3 Pricing Page (`/pricing`)
|
||||
|
||||
Three tiers, feature-complete across all. The difference is hosting and support.
|
||||
|
||||
**Self-Hosted (Free)**
|
||||
- All features, unlimited users
|
||||
- You host, you manage
|
||||
- Community support (GitHub, Discord)
|
||||
- "Perfect for developers, homelab enthusiasts, and teams who want full control."
|
||||
|
||||
**Cloud (Subscription — $XX/user/month)**
|
||||
- All features, unlimited
|
||||
- We host and manage everything
|
||||
- Automatic updates, backups, SSL
|
||||
- Email support
|
||||
- "For teams who want Officer without the DevOps."
|
||||
|
||||
**Enterprise (Custom)**
|
||||
- Everything in Cloud
|
||||
- SLA with guaranteed uptime
|
||||
- Priority support with dedicated account manager
|
||||
- Custom feature development
|
||||
- SSO/SAML integration
|
||||
- Audit logging
|
||||
- On-premises deployment assistance
|
||||
- "For organizations that need enterprise-grade guarantees."
|
||||
|
||||
**Below the pricing cards:**
|
||||
- FAQ section (Is it really free? Can I migrate between plans? What about data portability?)
|
||||
- "Need something custom?" → Contact form
|
||||
- "Building plugins?" → Marketplace waitlist signup
|
||||
|
||||
---
|
||||
|
||||
### 3.4 Enterprise Page (`/enterprise`)
|
||||
|
||||
**Audience**: IT decision-makers, CTOs, operations managers.
|
||||
|
||||
**Tone**: Professional, emphasizing reliability, security, and ROI.
|
||||
|
||||
**Sections:**
|
||||
|
||||
1. **Hero**: "The company intranet that works for you — literally."
|
||||
2. **Problem**: "Your team uses 12 different tools. None of them talk to each other. Officer replaces the glue."
|
||||
3. **Security**: "Self-hosted means your data never leaves your servers. Full audit logging. Role-based access. SOC 2 compliance roadmap."
|
||||
4. **ROI Calculator**: Interactive widget — input team size, estimated hours on repetitive tasks → shows annual savings
|
||||
5. **Consultancy**: "Our team builds custom integrations, plugins, and workflows tailored to your operations."
|
||||
6. **Case studies**: (placeholder for future customer stories)
|
||||
7. **CTA**: "Book a Demo" → Calendly or contact form
|
||||
|
||||
---
|
||||
|
||||
### 3.5 Open Source Page (`/open-source`)
|
||||
|
||||
**Audience**: Developers, contributors, plugin builders.
|
||||
|
||||
**Sections:**
|
||||
|
||||
1. **Hero**: "Built in the open. Extended by everyone."
|
||||
2. **Why Open Source**: Philosophy statement — transparency, community ownership, no vendor lock-in
|
||||
3. **Contributing**: Quick guide to getting started, link to CONTRIBUTING.md
|
||||
4. **Plugin Development**: Overview of the plugin system, link to docs
|
||||
5. **Marketplace Preview**: "Coming soon — build and sell plugins, themes, and automations. Earn money from your work."
|
||||
6. **GitHub Stats**: Stars, forks, contributors, recent commits
|
||||
7. **CTA**: "Star on GitHub" / "Join Discord"
|
||||
|
||||
---
|
||||
|
||||
## 4. Copy Bank
|
||||
|
||||
### Headlines (A/B test candidates)
|
||||
|
||||
**Automation-focused:**
|
||||
- "Your AI-powered operating system — everywhere."
|
||||
- "Stop doing. Start automating."
|
||||
- "The work that works itself."
|
||||
- "Automate everything. Miss nothing."
|
||||
|
||||
**For individuals:**
|
||||
- "Your second brain. But it actually does things."
|
||||
- "AI that doesn't just answer — it acts."
|
||||
- "Automate your life. Have more time to live it."
|
||||
|
||||
**For companies:**
|
||||
- "What if your team's busywork just... disappeared?"
|
||||
- "The company intranet that works for you — literally."
|
||||
- "Fortunes are lost to repetitive work every day. Meet the fix."
|
||||
- "Every employee deserves an AI assistant. Now they can have one."
|
||||
|
||||
**Open source angle:**
|
||||
- "Open source. Self-hosted. No strings attached."
|
||||
- "Your data. Your server. Your AI."
|
||||
- "The power of enterprise AI. The freedom of open source."
|
||||
|
||||
### Social Proof (to collect/create)
|
||||
|
||||
- GitHub stars count
|
||||
- "Used by X developers/companies"
|
||||
- Testimonials (collect after launch)
|
||||
- "Featured in [publications]" (aim for Hacker News, ProductHunt, etc.)
|
||||
|
||||
### Microcopy
|
||||
|
||||
- Install CTA: "Get Started — Free"
|
||||
- Cloud CTA: "Start your trial"
|
||||
- Enterprise CTA: "Book a demo"
|
||||
- GitHub CTA: "Star on GitHub"
|
||||
- Newsletter CTA: "Get updates"
|
||||
- Marketplace waitlist: "Join the waitlist"
|
||||
|
||||
---
|
||||
|
||||
## 5. Visual Identity for Marketing
|
||||
|
||||
### Design System Adaptation
|
||||
|
||||
The product uses a duck-themed design (teal, yellow, forest green, glass-morphism with pixel grid). The marketing site should feel like the same brand but optimized for conversion:
|
||||
|
||||
**Colors:**
|
||||
- Primary: `#F4C430` (Duck Yellow) — CTAs, highlights
|
||||
- Secondary: `#0891B2` (Duck Teal) — links, accents
|
||||
- Dark: `#14532D` (Duck Dark) — text, headings
|
||||
- Background: Soft cream/beige (`#F5F0E8`) or white with subtle grid texture
|
||||
- Dark mode: Support it, matching the product's dark theme
|
||||
|
||||
**Typography:**
|
||||
- Headings: Bold, system-ui stack with the same skewed/3D shadow effect as the logo (but subtler for readability)
|
||||
- Body: Clean sans-serif (Inter or system-ui), 18px base
|
||||
- Code: Monospace for install commands and API examples
|
||||
|
||||
**The Duck:**
|
||||
- Hero: Subtle walking animation (lightweight 2D sprite or CSS, not the 3D model — save loading time)
|
||||
- Scroll companion: Small duck that appears in corners, reacts to scroll
|
||||
- 404 page: Lost duck illustration
|
||||
- Loading states: Duck waddle animation
|
||||
|
||||
**Photography/Visuals:**
|
||||
- Product screenshots with the landscape backgrounds
|
||||
- Minimal mockups (no fake Chrome windows — just clean screenshots with rounded corners and shadow)
|
||||
- Feature diagrams: Simple, geometric, using brand colors
|
||||
|
||||
**Grid Pattern:**
|
||||
- Carry the pixel grid texture from the product into section backgrounds
|
||||
- Use it subtly — don't overwhelm the content
|
||||
|
||||
### Section Visual Hierarchy
|
||||
|
||||
| Section | Background | Text Color |
|
||||
|---------|-----------|------------|
|
||||
| Hero | landscape1.png with dark overlay | White |
|
||||
| Problem | White/cream | Dark green |
|
||||
| Solution | Subtle grid pattern | Dark green |
|
||||
| For You/Company | Split — light teal / light yellow | Dark |
|
||||
| How It Works | White | Dark |
|
||||
| Open Source | Dark (forest green) | Yellow/white |
|
||||
| Pricing | White/cream | Dark |
|
||||
| CTA | Teal gradient | White/yellow |
|
||||
|
||||
---
|
||||
|
||||
## 6. Demo Videos Plan
|
||||
|
||||
### Product Demo Reel (60s — for hero)
|
||||
|
||||
A fast-paced showcase that cycles through the major features:
|
||||
|
||||
| Time | Scene | Description |
|
||||
|------|-------|-------------|
|
||||
| 0-5s | Cold open | Tagline appears over landscape. Duck walks in. |
|
||||
| 5-12s | Chat | User asks AI to "summarize all PDFs in my project folder." AI responds with tool use, result appears. |
|
||||
| 12-20s | Files | File browser opens. User uploads files, previews images, plays audio. Quick montage. |
|
||||
| 20-30s | Automation | User creates a task. It runs automatically. Toast notification: "Task complete." |
|
||||
| 30-40s | Workspace | Multi-panel workspace assembles itself — chat + files + viewer. User drags to resize. |
|
||||
| 40-48s | Dashboard | Widgets dashboard: clock, weather, goals getting checked off, pomodoro timer running. |
|
||||
| 48-55s | Scale | "For you. For your team. For your company." — zoom out to show multiple users. |
|
||||
| 55-60s | CTA | Logo + "Open source. Self-hosted. Free forever." + URL |
|
||||
|
||||
### Feature-Specific Demos (30s each)
|
||||
|
||||
**AI Assistant Demo:**
|
||||
- Show real conversation with tool use
|
||||
- AI reads a file, suggests changes, user approves
|
||||
- Emphasis on the AI *doing things*, not just chatting
|
||||
|
||||
**File Management Demo:**
|
||||
- Upload → organize → preview → AI actions (OCR, transcribe)
|
||||
- Show the breadth of file types supported
|
||||
- yt-dlp download as a wow moment
|
||||
|
||||
**Automation Demo:**
|
||||
- Create a task that processes files automatically
|
||||
- Show it triggering on file upload
|
||||
- End with "Set it up once. It runs forever."
|
||||
|
||||
**Workspaces Demo:**
|
||||
- Start with empty screen
|
||||
- Build a workspace: add chat, files, viewer
|
||||
- Split panels, resize
|
||||
- "Your desk. Your way."
|
||||
|
||||
### Recording Guidelines
|
||||
|
||||
- **Resolution**: 1920x1080 for landscape, 1080x1920 for portrait (social)
|
||||
- **Browser**: Clean browser, no bookmarks bar, no extensions visible
|
||||
- **Data**: Use realistic-looking sample data (not lorem ipsum)
|
||||
- **Cursor**: Smooth, deliberate movements. No jitter.
|
||||
- **Speed**: 1.5x natural speed for repetitive parts, real-time for "wow" moments
|
||||
- **Music**: Upbeat instrumental for playful, ambient electronic for professional
|
||||
|
||||
---
|
||||
|
||||
## 7. Technical Implementation
|
||||
|
||||
### Stack Recommendation
|
||||
|
||||
The marketing site should be **separate from the main monorepo** — it's a public website with different deployment, SEO, and performance requirements.
|
||||
|
||||
**Recommended stack:**
|
||||
- **Framework**: Astro (static-first, great SEO, supports React islands for interactive parts)
|
||||
- **Styling**: Tailwind CSS (matches the product's design system)
|
||||
- **Animations**: Framer Motion (for scroll-triggered animations)
|
||||
- **Hosting**: Vercel or Cloudflare Pages (fast global CDN)
|
||||
- **CMS**: Markdown files for blog posts (future)
|
||||
- **Analytics**: Plausible or PostHog (privacy-friendly)
|
||||
|
||||
**Alternative**: If the team prefers to keep everything in the monorepo's React ecosystem, a Next.js or Vite app could work. But Astro's static output and built-in SEO features make it better for a marketing site.
|
||||
|
||||
### Project Location
|
||||
|
||||
Create at `/home/pastilhas/projects/officer.dev/website/` — separate from the monorepo but within the project directory.
|
||||
|
||||
### SEO Strategy
|
||||
|
||||
**Target keywords:**
|
||||
- "self-hosted AI platform"
|
||||
- "open source AI assistant"
|
||||
- "AI-powered intranet"
|
||||
- "personal AI operating system"
|
||||
- "self-hosted automation"
|
||||
- "open source alternative to [Claude Work/Notion AI/etc.]"
|
||||
- "AI file management"
|
||||
|
||||
**Technical SEO:**
|
||||
- Static HTML pages (Astro)
|
||||
- Proper meta tags, OpenGraph images per page
|
||||
- JSON-LD structured data
|
||||
- Sitemap.xml
|
||||
- Fast Core Web Vitals (landscape images need lazy loading + WebP conversion)
|
||||
|
||||
### Performance Considerations
|
||||
|
||||
- landscape1.png is 16MB — must be converted to WebP/AVIF and served responsive
|
||||
- The 3D duck model (40MB total) should NOT be on the marketing site — use a lightweight 2D animation instead
|
||||
- Use the rubber-duck.png (1.6MB) at reduced size for the duck character
|
||||
- Lazy load everything below the fold
|
||||
|
||||
---
|
||||
|
||||
## 8. Launch Considerations
|
||||
|
||||
### Pre-Launch Checklist
|
||||
|
||||
- [ ] Marketing site live with all sections
|
||||
- [ ] Product demo video recorded and embedded
|
||||
- [ ] GitHub repo public with README, CONTRIBUTING.md, LICENSE
|
||||
- [ ] Installation script (`install.officer.dev`) working
|
||||
- [ ] Documentation site (even minimal) live
|
||||
- [ ] Discord/community channel created
|
||||
- [ ] Social accounts created (Twitter/X, LinkedIn)
|
||||
- [ ] ProductHunt launch page drafted
|
||||
- [ ] Hacker News "Show HN" post drafted
|
||||
- [ ] Email waitlist for cloud/marketplace
|
||||
|
||||
### Launch Channels
|
||||
|
||||
| Channel | Content | Timing |
|
||||
|---------|---------|--------|
|
||||
| Hacker News | "Show HN: Officer — open-source, AI-powered OS for automating your life" | Day 1 |
|
||||
| ProductHunt | Full launch with screenshots, video, maker story | Day 1 |
|
||||
| Reddit | r/selfhosted, r/homelab, r/opensource, r/artificial | Day 1 |
|
||||
| Twitter/X | Thread: "I built an OS that automates my life. It's open source." | Day 1 |
|
||||
| LinkedIn | Professional angle: "Every company wastes $X on repetitive work" | Day 2 |
|
||||
| Dev.to / Hashnode | Technical deep-dive blog post | Week 1 |
|
||||
| YouTube | Full demo video (5min) | Week 1 |
|
||||
|
||||
### Post-Launch
|
||||
|
||||
- Monitor GitHub issues and community channels
|
||||
- Publish weekly blog posts (features, tutorials, philosophy)
|
||||
- Start marketplace waitlist campaign
|
||||
- Collect testimonials from early adopters
|
||||
- Begin enterprise outreach
|
||||
|
||||
---
|
||||
|
||||
## Appendix: Competitor Landscape
|
||||
|
||||
| Product | What it is | Officer's advantage |
|
||||
|---------|-----------|-------------------|
|
||||
| **Notion** | Wiki + project management | Officer has AI that acts, not just organizes. Self-hosted. |
|
||||
| **Obsidian** | Markdown knowledge base | Officer is broader — files, AI, automation, not just notes. |
|
||||
| **Nextcloud** | Self-hosted file sync | Officer has native AI, automation, and workspaces. |
|
||||
| **n8n** | Workflow automation | Officer combines automation with AI + file management + UI. |
|
||||
| **Claude Work** | Enterprise AI chat | Officer is open source, self-hosted, and more extensible. |
|
||||
| **OpenClaw** | Open source AI tools | Officer is friendlier, more polished, broader scope. |
|
||||
| **Home Assistant** | Home automation | Different domain, but similar self-hosted philosophy. Potential integration. |
|
||||
|
||||
Officer's unique position: **No one else combines AI + files + automation + workspaces in a single self-hosted platform.** That's the moat.
|
||||
+1208
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import { Server, Wrench, Loader2 } from 'lucide-react';
|
||||
import { Server, Wrench, Loader2, RefreshCw, Trash2 } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
import { useGlobal } from 'hooks/useGlobal';
|
||||
import { usePanelChannel } from 'hooks/usePanelChannel';
|
||||
import { Button } from '@/components/ui/button';
|
||||
@@ -14,7 +15,6 @@ import {
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from '@/components/ui/alert-dialog';
|
||||
import { CommandBlock } from '@/components/CommandBlock';
|
||||
import { useResources, getResourceCategory, type Resource, type PingResult } from '@/state/useResources';
|
||||
import { RUN_COMMAND_CHANNEL, type RunCommandState } from './run-command-channel';
|
||||
|
||||
@@ -135,29 +135,133 @@ type LocalAvailabilitySectionProps = {
|
||||
onRun: (command: string) => void;
|
||||
};
|
||||
|
||||
const LocalAvailabilitySection = ({ resource, onRun }: LocalAvailabilitySectionProps) => (
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold text-duck-dark mb-3">Local Availability</h3>
|
||||
<div className="mb-3">
|
||||
type ResourceAction = 'install' | 'uninstall' | 'verify' | 'update' | 'manage';
|
||||
|
||||
const LocalAvailabilitySection = ({ resource, onRun }: LocalAvailabilitySectionProps) => {
|
||||
const { runCommand } = useResources();
|
||||
const [runningAction, setRunningAction] = useState<ResourceAction | null>(null);
|
||||
|
||||
const isSudo = (cmd: string) => cmd.trimStart().startsWith('sudo');
|
||||
|
||||
const handleAction = async (action: ResourceAction, command: string) => {
|
||||
if (isSudo(command)) {
|
||||
onRun(command);
|
||||
return;
|
||||
}
|
||||
setRunningAction(action);
|
||||
try {
|
||||
const result = await runCommand(resource.id, action);
|
||||
if (result.exitCode === 0) {
|
||||
toast.success('Command completed successfully');
|
||||
} else {
|
||||
toast.error(result.output || `Command failed (exit code ${result.exitCode})`, { duration: 8000 });
|
||||
}
|
||||
} catch {
|
||||
toast.error('Failed to run command');
|
||||
} finally {
|
||||
setRunningAction(null);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
{resource.installed ? (
|
||||
<span className="text-xs bg-green-100 text-green-700 rounded-full px-2 py-0.5">
|
||||
Installed{resource.version ? ` (${resource.version})` : ''}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-xs bg-duck-dark/5 text-duck-dark/40 rounded-full px-2 py-0.5">Not installed</span>
|
||||
<>
|
||||
<div>
|
||||
<span className="text-xs bg-green-100 text-green-700 rounded-full px-2 py-0.5">Installed</span>
|
||||
</div>
|
||||
{resource.version && (
|
||||
<div className="flex items-center gap-2">
|
||||
{resource.updateCommand && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-6 text-xs cursor-pointer"
|
||||
onClick={() => handleAction('update', resource.updateCommand!)}
|
||||
disabled={!!runningAction}
|
||||
>
|
||||
<RefreshCw className={`h-3 w-3 mr-1 ${runningAction === 'update' ? 'animate-spin' : ''}`} />
|
||||
Update
|
||||
</Button>
|
||||
)}
|
||||
<span className="text-xs text-duck-dark/50 dark:text-foreground/50">{resource.version}</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center gap-1.5">
|
||||
{!resource.version && resource.updateCommand && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-6 text-xs cursor-pointer"
|
||||
onClick={() => handleAction('update', resource.updateCommand!)}
|
||||
disabled={!!runningAction}
|
||||
>
|
||||
<RefreshCw className={`h-3 w-3 mr-1 ${runningAction === 'update' ? 'animate-spin' : ''}`} />
|
||||
Update
|
||||
</Button>
|
||||
)}
|
||||
{resource.verifyCommand && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-6 text-xs cursor-pointer"
|
||||
onClick={() => handleAction('verify', resource.verifyCommand!)}
|
||||
disabled={!!runningAction}
|
||||
>
|
||||
{runningAction === 'verify' && <Loader2 className="h-3 w-3 mr-1 animate-spin" />}
|
||||
Verify
|
||||
</Button>
|
||||
)}
|
||||
{resource.manageCommand && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-6 text-xs cursor-pointer"
|
||||
onClick={() => handleAction('manage', resource.manageCommand!)}
|
||||
disabled={!!runningAction}
|
||||
>
|
||||
{runningAction === 'manage' && <Loader2 className="h-3 w-3 mr-1 animate-spin" />}
|
||||
Manage
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col gap-3">
|
||||
{resource.installCommand && <CommandBlock label="Install" command={resource.installCommand} onRun={onRun} />}
|
||||
{resource.uninstallCommand && (
|
||||
<CommandBlock label="Uninstall" command={resource.uninstallCommand} onRun={onRun} />
|
||||
<div className="flex items-center mt-1.5">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-6 text-xs cursor-pointer text-red-500 hover:text-red-600 border-red-500/30 hover:border-red-500/50 hover:bg-red-500/5"
|
||||
onClick={() => handleAction('uninstall', resource.uninstallCommand!)}
|
||||
disabled={!!runningAction}
|
||||
>
|
||||
{runningAction === 'uninstall' ? (
|
||||
<Loader2 className="h-3 w-3 mr-1 animate-spin" />
|
||||
) : (
|
||||
<Trash2 className="h-3 w-3 mr-1" />
|
||||
)}
|
||||
{resource.manageCommand && <CommandBlock label="Manage" command={resource.manageCommand} onRun={onRun} />}
|
||||
{resource.verifyCommand && <CommandBlock label="Verify" command={resource.verifyCommand} onRun={onRun} />}
|
||||
{resource.updateCommand && <CommandBlock label="Update" command={resource.updateCommand} onRun={onRun} />}
|
||||
Uninstall
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-xs bg-duck-dark/5 text-duck-dark/40 rounded-full px-2 py-0.5">Not installed</span>
|
||||
{resource.installCommand && (
|
||||
<Button
|
||||
size="sm"
|
||||
className="h-6 text-xs bg-duck-teal text-duck-yellow hover:bg-duck-teal/90 cursor-pointer"
|
||||
onClick={() => handleAction('install', resource.installCommand!)}
|
||||
disabled={runningAction === 'install'}
|
||||
>
|
||||
{runningAction === 'install' ? 'Installing...' : 'Install'}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
type CatalogCardProps = {
|
||||
resource: Resource;
|
||||
@@ -306,18 +410,12 @@ const ResourceDetail = ({ resource }: { resource: Resource }) => {
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Run with elevated privileges</AlertDialogTitle>
|
||||
<AlertDialogDescription asChild>
|
||||
<div>
|
||||
You are about to run a command with elevated privileges (sudo)
|
||||
<br />
|
||||
<span className="text-red-500">
|
||||
in the host machine.
|
||||
<br />
|
||||
ARE YOU SURE?
|
||||
</span>
|
||||
</div>
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<p className="text-sm text-duck-dark/70 dark:text-foreground/70">
|
||||
For this operation the script must be run with elevated privileges (sudo) on the host machine.
|
||||
<br />
|
||||
Not to worry, though, we wrote it and battle tested it ourselves.
|
||||
</p>
|
||||
<code className="text-sm font-mono bg-[#1a1a2e] text-[#e0e0e0] rounded-lg px-3 py-2 break-all">{confirmCommand}</code>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel className="cursor-pointer">Cancel</AlertDialogCancel>
|
||||
|
||||
@@ -58,5 +58,11 @@ export const useResources = () => {
|
||||
return client.post<PingResult>(`/server-settings/resources/${id}/ping`, { url });
|
||||
};
|
||||
|
||||
return { resources, isLoading, saveConnectionConfig, pingResource };
|
||||
const runCommand = async (id: string, action: string) => {
|
||||
const result = await client.post<{ exitCode: number; output: string }>(`/server-settings/resources/${id}/run`, { action });
|
||||
queryClient.invalidateQueries({ queryKey: RESOURCES_KEY });
|
||||
return result;
|
||||
};
|
||||
|
||||
return { resources, isLoading, saveConnectionConfig, pingResource, runCommand };
|
||||
};
|
||||
|
||||
@@ -198,20 +198,22 @@ function buildConnectionConfig(
|
||||
return { url: `http://127.0.0.1:${port ?? resource.port}` };
|
||||
}
|
||||
|
||||
async function loadResources(): Promise<Resource[]> {
|
||||
async function parseResources() {
|
||||
const dir = getResourcesDir();
|
||||
if (!existsSync(dir)) return [];
|
||||
const [files, config] = await Promise.all([readdir(dir), readConfig()]);
|
||||
const files = await readdir(dir);
|
||||
const serviceFiles = files.filter((f) => f.startsWith('SERVICE_') && f.endsWith('.md'));
|
||||
|
||||
const parsed = await Promise.all(
|
||||
return Promise.all(
|
||||
serviceFiles.map(async (filename) => {
|
||||
const content = await Bun.file(`${dir}/${filename}`).text();
|
||||
return parseResourceFile(filename, content);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
const resources = await Promise.all(
|
||||
async function loadResources(): Promise<Resource[]> {
|
||||
const [parsed, config] = await Promise.all([parseResources(), readConfig()]);
|
||||
return Promise.all(
|
||||
parsed.map(async (r) => {
|
||||
const configUrl = config[r.id]?.url;
|
||||
const status = await checkResourceStatus({ resource: r, configUrl });
|
||||
@@ -219,8 +221,6 @@ async function loadResources(): Promise<Resource[]> {
|
||||
return { ...r, ...status, connectionConfig };
|
||||
}),
|
||||
);
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
||||
export const resourcesRouter = createRouter();
|
||||
@@ -290,6 +290,42 @@ resourcesRouter.post('/error-log', async (ctx) => {
|
||||
return ctx.json({ filePath });
|
||||
});
|
||||
|
||||
resourcesRouter.post('/:id/run', async (ctx) => {
|
||||
const id = ctx.req.param('id');
|
||||
const { action } = await ctx.req.json<{ action: string }>();
|
||||
|
||||
const parsed = await parseResources();
|
||||
const resource = parsed.find((r) => r.id === id);
|
||||
if (!resource) return ctx.json({ error: 'Resource not found' }, 404);
|
||||
|
||||
const commands: Record<string, string | null> = {
|
||||
install: resource.installCommand,
|
||||
uninstall: resource.uninstallCommand,
|
||||
verify: resource.verifyCommand,
|
||||
update: resource.updateCommand,
|
||||
manage: resource.manageCommand,
|
||||
};
|
||||
|
||||
const command = commands[action];
|
||||
if (!command) return ctx.json({ error: `No ${action} command for this resource` }, 400);
|
||||
|
||||
if (command.trimStart().startsWith('sudo')) {
|
||||
return ctx.json({ error: 'Sudo commands must run in terminal' }, 400);
|
||||
}
|
||||
|
||||
try {
|
||||
const proc = Bun.spawn(['sh', '-c', command], { stdout: 'pipe', stderr: 'pipe' });
|
||||
const [stdout, stderr] = await Promise.all([
|
||||
new Response(proc.stdout).text(),
|
||||
new Response(proc.stderr).text(),
|
||||
]);
|
||||
await proc.exited;
|
||||
return ctx.json({ exitCode: proc.exitCode, output: (stdout + stderr).trim() });
|
||||
} catch {
|
||||
return ctx.json({ exitCode: 1, output: 'Failed to execute command' });
|
||||
}
|
||||
});
|
||||
|
||||
resourcesRouter.get('/:id', async (ctx) => {
|
||||
const resources = await loadResources();
|
||||
const resource = resources.find((r) => r.id === ctx.req.param('id'));
|
||||
|
||||
Reference in New Issue
Block a user