chore: cleanup unused files and update gitignore
Some checks failed
ci/woodpecker/push/build Pipeline failed
Some checks failed
ci/woodpecker/push/build Pipeline failed
- Remove MONETIZATION.md and README.md - Add dist/ to gitignore Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
ac04d7f346
commit
a045da82b7
6 changed files with 18 additions and 191 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -10,4 +10,7 @@ node_modules/
|
||||||
.vscode/
|
.vscode/
|
||||||
*.swp
|
*.swp
|
||||||
|
|
||||||
|
dist/
|
||||||
|
|
||||||
tmp
|
tmp
|
||||||
|
.vite/
|
||||||
|
|
|
||||||
16
Dockerfile
16
Dockerfile
|
|
@ -1,16 +1,20 @@
|
||||||
FROM node:22-alpine AS studio
|
FROM node:22-alpine AS frontends
|
||||||
WORKDIR /app/studio
|
WORKDIR /app
|
||||||
COPY studio/package*.json ./
|
COPY frontends/package*.json ./
|
||||||
|
COPY frontends/studio/package*.json ./studio/
|
||||||
|
COPY frontends/owner-tools/package*.json ./owner-tools/
|
||||||
|
COPY frontends/ui/package.json ./ui/
|
||||||
RUN npm ci
|
RUN npm ci
|
||||||
COPY studio/ ./
|
COPY frontends/ ./
|
||||||
RUN npm run build
|
RUN npm run build --workspace=studio --workspace=owner-tools
|
||||||
|
|
||||||
FROM golang:1.24-alpine AS builder
|
FROM golang:1.24-alpine AS builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY go.mod go.sum ./
|
COPY go.mod go.sum ./
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
COPY . .
|
COPY . .
|
||||||
COPY --from=studio /app/studio/dist ./studio/dist
|
COPY --from=frontends /app/studio/dist ./frontends/studio/dist
|
||||||
|
COPY --from=frontends /internal/tenant/assets/js/owner-tools.js ./internal/tenant/assets/js/owner-tools.js
|
||||||
RUN CGO_ENABLED=0 go build -o writekit .
|
RUN CGO_ENABLED=0 go build -o writekit .
|
||||||
|
|
||||||
FROM alpine:3.21
|
FROM alpine:3.21
|
||||||
|
|
|
||||||
121
MONETIZATION.md
121
MONETIZATION.md
|
|
@ -1,121 +0,0 @@
|
||||||
# WriteKit Monetization
|
|
||||||
|
|
||||||
## Tiers
|
|
||||||
|
|
||||||
| Tier | Price | Billing |
|
|
||||||
|------|-------|---------|
|
|
||||||
| Free | $0 | - |
|
|
||||||
| Pro | $5/mo or $49/year | Lemon Squeezy |
|
|
||||||
|
|
||||||
## Feature Matrix
|
|
||||||
|
|
||||||
| Feature | Free | Pro |
|
|
||||||
|---------|------|-----|
|
|
||||||
| Subdomain (you.writekit.dev) | Yes | Yes |
|
|
||||||
| Custom domain | No | Yes |
|
|
||||||
| "Powered by WriteKit" badge | Required | Hidden |
|
|
||||||
| Analytics retention | 7 days | 90 days |
|
|
||||||
| API requests | 100/hour | 1000/hour |
|
|
||||||
| Webhooks | 3 endpoints | 10 endpoints |
|
|
||||||
| Webhook deliveries | 100/day | 1000/day |
|
|
||||||
| Plugins | 3 max | 10 max |
|
|
||||||
| Plugin executions | 1000/day | 10000/day |
|
|
||||||
| Posts | Unlimited | Unlimited |
|
|
||||||
| Assets | Unlimited | Unlimited |
|
|
||||||
| Comments/Reactions | Unlimited | Unlimited |
|
|
||||||
|
|
||||||
## Upgrade Triggers
|
|
||||||
|
|
||||||
1. **Custom domain** - Primary trigger, most valuable to users
|
|
||||||
2. **Remove badge** - Secondary, vanity upgrade
|
|
||||||
3. **Analytics depth** - 7 days feels limiting for serious bloggers
|
|
||||||
4. **Rate limits** - For power users/headless CMS use case
|
|
||||||
|
|
||||||
## Positioning
|
|
||||||
|
|
||||||
**Tagline:** "Your blog, your domain, your data."
|
|
||||||
|
|
||||||
**Key messages:**
|
|
||||||
- No paywalls, no algorithms, no surprises
|
|
||||||
- 70% cheaper than Ghost ($5 vs $18/mo)
|
|
||||||
- Own your content, export anytime
|
|
||||||
- API-first, developer-friendly
|
|
||||||
|
|
||||||
## Implementation
|
|
||||||
|
|
||||||
### Backend Config
|
|
||||||
|
|
||||||
```go
|
|
||||||
// internal/config/tiers.go
|
|
||||||
type Tier string
|
|
||||||
|
|
||||||
const (
|
|
||||||
TierFree Tier = "free"
|
|
||||||
TierPro Tier = "pro"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TierConfig struct {
|
|
||||||
Price int // cents/month
|
|
||||||
AnnualPrice int // cents/year
|
|
||||||
CustomDomain bool
|
|
||||||
BadgeRequired bool
|
|
||||||
AnalyticsRetention int // days
|
|
||||||
APIRateLimit int // requests/hour
|
|
||||||
MaxWebhooks int
|
|
||||||
WebhookDeliveries int // per day
|
|
||||||
MaxPlugins int
|
|
||||||
PluginExecutions int // per day
|
|
||||||
}
|
|
||||||
|
|
||||||
var Tiers = map[Tier]TierConfig{
|
|
||||||
TierFree: {
|
|
||||||
Price: 0,
|
|
||||||
AnnualPrice: 0,
|
|
||||||
CustomDomain: false,
|
|
||||||
BadgeRequired: true,
|
|
||||||
AnalyticsRetention: 7,
|
|
||||||
APIRateLimit: 100,
|
|
||||||
MaxWebhooks: 3,
|
|
||||||
WebhookDeliveries: 100,
|
|
||||||
MaxPlugins: 3,
|
|
||||||
PluginExecutions: 1000,
|
|
||||||
},
|
|
||||||
TierPro: {
|
|
||||||
Price: 500, // $5
|
|
||||||
AnnualPrice: 4900, // $49
|
|
||||||
CustomDomain: true,
|
|
||||||
BadgeRequired: false,
|
|
||||||
AnalyticsRetention: 90,
|
|
||||||
APIRateLimit: 1000,
|
|
||||||
MaxWebhooks: 10,
|
|
||||||
WebhookDeliveries: 1000,
|
|
||||||
MaxPlugins: 10,
|
|
||||||
PluginExecutions: 10000,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Database
|
|
||||||
|
|
||||||
Add to `tenants` table:
|
|
||||||
```sql
|
|
||||||
tier TEXT NOT NULL DEFAULT 'free'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Frontend
|
|
||||||
|
|
||||||
Update `BillingPage.tsx` with:
|
|
||||||
- Current plan display
|
|
||||||
- Feature comparison
|
|
||||||
- Upgrade button → Lemon Squeezy checkout
|
|
||||||
|
|
||||||
### Enforcement Points
|
|
||||||
|
|
||||||
| Feature | File | Check |
|
|
||||||
|---------|------|-------|
|
|
||||||
| Custom domain | `server/domain.go` | Block if tier != pro |
|
|
||||||
| Badge | Blog templates | Show if tier == free |
|
|
||||||
| Analytics | `tenant/analytics.go` | Filter by retention days |
|
|
||||||
| API rate limit | `server/middleware.go` | Rate limiter per tier |
|
|
||||||
| Webhooks count | `tenant/webhooks.go` | Check on create |
|
|
||||||
| Plugins count | `tenant/plugins.go` | Check on create |
|
|
||||||
61
README.md
61
README.md
|
|
@ -1,61 +0,0 @@
|
||||||
# WriteKit - Local Development
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
- Docker & Docker Compose
|
|
||||||
- GitHub OAuth App (for login)
|
|
||||||
|
|
||||||
## Setup GitHub OAuth
|
|
||||||
1. Go to https://github.com/settings/developers
|
|
||||||
2. New OAuth App:
|
|
||||||
- Name: `WriteKit Local`
|
|
||||||
- Homepage: `http://writekit.lvh.me`
|
|
||||||
- Callback: `http://writekit.lvh.me/auth/github/callback`
|
|
||||||
3. Copy Client ID and Secret
|
|
||||||
|
|
||||||
## Run
|
|
||||||
```bash
|
|
||||||
# Set OAuth credentials
|
|
||||||
export GITHUB_CLIENT_ID=your_client_id
|
|
||||||
export GITHUB_CLIENT_SECRET=your_client_secret
|
|
||||||
|
|
||||||
# Start
|
|
||||||
docker compose up --build
|
|
||||||
```
|
|
||||||
|
|
||||||
Or create `.env` file:
|
|
||||||
```
|
|
||||||
GITHUB_CLIENT_ID=your_client_id
|
|
||||||
GITHUB_CLIENT_SECRET=your_client_secret
|
|
||||||
```
|
|
||||||
|
|
||||||
## Access
|
|
||||||
- **Platform**: http://writekit.lvh.me
|
|
||||||
- **Traefik dashboard**: http://localhost:8080
|
|
||||||
- **MinIO console**: http://localhost:9001 (minioadmin/minioadmin)
|
|
||||||
|
|
||||||
## Create a demo
|
|
||||||
```bash
|
|
||||||
curl -X POST http://writekit.lvh.me/api/demo
|
|
||||||
```
|
|
||||||
Returns subdomain like `demo-abc123.writekit.lvh.me` - works automatically, no hosts file needed.
|
|
||||||
|
|
||||||
## Environment Variables
|
|
||||||
|
|
||||||
### Required
|
|
||||||
| Variable | Description |
|
|
||||||
|----------|-------------|
|
|
||||||
| `DATABASE_URL` | PostgreSQL connection string |
|
|
||||||
| `DOMAIN` | Base domain |
|
|
||||||
| `BASE_URL` | Full URL for OAuth callbacks |
|
|
||||||
| `SESSION_SECRET` | Cookie encryption (32+ chars) |
|
|
||||||
| `GITHUB_CLIENT_ID` | GitHub OAuth client ID |
|
|
||||||
| `GITHUB_CLIENT_SECRET` | GitHub OAuth secret |
|
|
||||||
|
|
||||||
### Optional
|
|
||||||
| Variable | Description |
|
|
||||||
|----------|-------------|
|
|
||||||
| `GOOGLE_CLIENT_ID/SECRET` | Google OAuth |
|
|
||||||
| `DISCORD_CLIENT_ID/SECRET` | Discord OAuth |
|
|
||||||
| `R2_*` | Cloudflare R2 storage |
|
|
||||||
| `IMAGINARY_URL` | Image processing service |
|
|
||||||
| `CLOUDFLARE_API_TOKEN/ZONE_ID` | Analytics |
|
|
||||||
|
|
@ -36,7 +36,7 @@ export default defineConfig(({ command }) => ({
|
||||||
formats: ['iife'],
|
formats: ['iife'],
|
||||||
fileName: () => 'owner-tools.js'
|
fileName: () => 'owner-tools.js'
|
||||||
},
|
},
|
||||||
outDir: '../../internal/build/assets/js',
|
outDir: '../../internal/tenant/assets/js',
|
||||||
emptyOutDir: false
|
emptyOutDir: false
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { useState, useCallback, useRef, useEffect } from 'react'
|
||||||
import { getLanguageIconUrl, getLanguageDisplayName, SUPPORTED_LANGUAGES } from './icons'
|
import { getLanguageIconUrl, getLanguageDisplayName, SUPPORTED_LANGUAGES } from './icons'
|
||||||
import { Icons } from '../../../shared/Icons'
|
import { Icons } from '../../../shared/Icons'
|
||||||
|
|
||||||
export function CodeBlockView({ node, updateAttributes, extension }: NodeViewProps) {
|
export function CodeBlockView({ node, updateAttributes }: NodeViewProps) {
|
||||||
const { language, title } = node.attrs
|
const { language, title } = node.attrs
|
||||||
const [showLanguageMenu, setShowLanguageMenu] = useState(false)
|
const [showLanguageMenu, setShowLanguageMenu] = useState(false)
|
||||||
const [copied, setCopied] = useState(false)
|
const [copied, setCopied] = useState(false)
|
||||||
|
|
@ -161,7 +161,9 @@ export function CodeBlockView({ node, updateAttributes, extension }: NodeViewPro
|
||||||
|
|
||||||
{/* Code content */}
|
{/* Code content */}
|
||||||
<pre className="!mt-0 !rounded-t-none">
|
<pre className="!mt-0 !rounded-t-none">
|
||||||
<NodeViewContent as="code" className={language ? `language-${language}` : ''} />
|
<code className={language ? `language-${language}` : ''}>
|
||||||
|
<NodeViewContent />
|
||||||
|
</code>
|
||||||
</pre>
|
</pre>
|
||||||
</NodeViewWrapper>
|
</NodeViewWrapper>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue