@nuraly/lumenjs 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/native-auth.d.ts +9 -0
- package/dist/auth/native-auth.js +49 -2
- package/dist/auth/routes/login.js +24 -1
- package/dist/auth/routes/totp.d.ts +22 -0
- package/dist/auth/routes/totp.js +232 -0
- package/dist/auth/routes.js +14 -0
- package/dist/auth/token.js +2 -2
- package/dist/build/build-server.d.ts +2 -1
- package/dist/build/build-server.js +10 -1
- package/dist/build/build.js +13 -4
- package/dist/build/scan.d.ts +1 -0
- package/dist/build/scan.js +2 -1
- package/dist/build/serve.js +131 -11
- package/dist/dev-server/config.js +18 -1
- package/dist/dev-server/index-html.d.ts +1 -0
- package/dist/dev-server/index-html.js +4 -1
- package/dist/dev-server/plugins/vite-plugin-routes.js +3 -2
- package/dist/dev-server/plugins/vite-plugin-virtual-modules.js +34 -6
- package/dist/dev-server/server.js +146 -88
- package/dist/dev-server/ssr-render.js +10 -2
- package/dist/editor/ai/backend.js +11 -2
- package/dist/editor/ai/deepseek-client.d.ts +7 -0
- package/dist/editor/ai/deepseek-client.js +113 -0
- package/dist/editor/ai/opencode-client.d.ts +1 -1
- package/dist/editor/ai/opencode-client.js +21 -47
- package/dist/editor/ai-chat-panel.js +27 -1
- package/dist/editor/editor-bridge.js +2 -1
- package/dist/editor/overlay-hmr.js +2 -1
- package/dist/runtime/app-shell.d.ts +1 -1
- package/dist/runtime/app-shell.js +1 -0
- package/dist/runtime/island.d.ts +16 -0
- package/dist/runtime/island.js +80 -0
- package/dist/runtime/router-hydration.js +9 -2
- package/dist/runtime/router.d.ts +3 -1
- package/dist/runtime/router.js +49 -1
- package/dist/runtime/webrtc.d.ts +44 -0
- package/dist/runtime/webrtc.js +263 -13
- package/dist/shared/dom-shims.js +4 -2
- package/dist/shared/types.d.ts +1 -0
- package/dist/storage/adapters/s3.js +6 -3
- package/package.json +33 -7
- package/templates/social/api/posts/[id].ts +0 -14
- package/templates/social/api/posts.ts +0 -11
- package/templates/social/api/profile/[username].ts +0 -10
- package/templates/social/api/upload.ts +0 -19
- package/templates/social/data/migrations/001_init.sql +0 -78
- package/templates/social/data/migrations/002_add_image_url.sql +0 -1
- package/templates/social/data/migrations/003_auth.sql +0 -7
- package/templates/social/docs/architecture.md +0 -76
- package/templates/social/docs/components.md +0 -100
- package/templates/social/docs/data.md +0 -89
- package/templates/social/docs/pages.md +0 -96
- package/templates/social/docs/theming.md +0 -52
- package/templates/social/lib/media.ts +0 -130
- package/templates/social/lumenjs.auth.ts +0 -21
- package/templates/social/lumenjs.config.ts +0 -3
- package/templates/social/package.json +0 -5
- package/templates/social/pages/_layout.ts +0 -239
- package/templates/social/pages/apps/[id].ts +0 -173
- package/templates/social/pages/apps/index.ts +0 -116
- package/templates/social/pages/auth/login.ts +0 -92
- package/templates/social/pages/bookmarks.ts +0 -57
- package/templates/social/pages/explore.ts +0 -73
- package/templates/social/pages/index.ts +0 -351
- package/templates/social/pages/messages.ts +0 -298
- package/templates/social/pages/new.ts +0 -77
- package/templates/social/pages/notifications.ts +0 -73
- package/templates/social/pages/post/[id].ts +0 -124
- package/templates/social/pages/profile/[username].ts +0 -100
- package/templates/social/pages/settings/accessibility.ts +0 -153
- package/templates/social/pages/settings/account.ts +0 -260
- package/templates/social/pages/settings/help.ts +0 -141
- package/templates/social/pages/settings/language.ts +0 -103
- package/templates/social/pages/settings/privacy.ts +0 -183
- package/templates/social/pages/settings/security.ts +0 -133
- package/templates/social/pages/settings.ts +0 -185
|
@@ -61,16 +61,19 @@ export class S3StorageAdapter {
|
|
|
61
61
|
const mimeType = options?.mimeType ?? 'application/octet-stream';
|
|
62
62
|
const acl = options?.acl ?? 'public-read';
|
|
63
63
|
const { s3, PutObjectCommand } = await this.getClient();
|
|
64
|
-
|
|
64
|
+
const cmd = {
|
|
65
65
|
Bucket: this.options.bucket,
|
|
66
66
|
Key: key,
|
|
67
67
|
Body: data,
|
|
68
68
|
ContentType: mimeType,
|
|
69
|
-
ACL: acl,
|
|
70
69
|
...(options?.fileName
|
|
71
70
|
? { ContentDisposition: `inline; filename="${options.fileName.replace(/[\r\n"\\]/g, '_')}"` }
|
|
72
71
|
: {}),
|
|
73
|
-
}
|
|
72
|
+
};
|
|
73
|
+
// R2 and some S3-compatible APIs don't support ACL
|
|
74
|
+
if (!this.options.endpoint)
|
|
75
|
+
cmd.ACL = acl;
|
|
76
|
+
await s3.send(new PutObjectCommand(cmd));
|
|
74
77
|
return {
|
|
75
78
|
key,
|
|
76
79
|
url: this.publicUrl(key),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuraly/lumenjs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Full-stack Lit web component framework with file-based routing, server loaders, SSR, and API routes",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cli.js",
|
|
@@ -43,18 +43,20 @@
|
|
|
43
43
|
"license": "MIT",
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@lit-labs/ssr": "^3.2.0",
|
|
46
|
-
"better-sqlite3": "^12.8.0",
|
|
47
|
-
"codejar": "^4.2.0",
|
|
48
46
|
"glob": "^10.3.0",
|
|
49
47
|
"lit": "^3.1.0",
|
|
50
|
-
"pg": "^8.20.0",
|
|
51
|
-
"socket.io": "^4.8.3",
|
|
52
|
-
"socket.io-client": "^4.8.3",
|
|
53
48
|
"vite": "^5.4.0"
|
|
54
49
|
},
|
|
55
50
|
"peerDependencies": {
|
|
56
51
|
"@aws-sdk/client-s3": "^3.0.0",
|
|
57
|
-
"@aws-sdk/s3-request-presigner": "^3.0.0"
|
|
52
|
+
"@aws-sdk/s3-request-presigner": "^3.0.0",
|
|
53
|
+
"better-sqlite3": "^12.8.0",
|
|
54
|
+
"codejar": "^4.2.0",
|
|
55
|
+
"otplib": "^12.0.0",
|
|
56
|
+
"pg": "^8.0.0",
|
|
57
|
+
"qrcode": "^1.5.0",
|
|
58
|
+
"socket.io": "^4.0.0",
|
|
59
|
+
"socket.io-client": "^4.0.0"
|
|
58
60
|
},
|
|
59
61
|
"peerDependenciesMeta": {
|
|
60
62
|
"@aws-sdk/client-s3": {
|
|
@@ -62,12 +64,36 @@
|
|
|
62
64
|
},
|
|
63
65
|
"@aws-sdk/s3-request-presigner": {
|
|
64
66
|
"optional": true
|
|
67
|
+
},
|
|
68
|
+
"better-sqlite3": {
|
|
69
|
+
"optional": true
|
|
70
|
+
},
|
|
71
|
+
"codejar": {
|
|
72
|
+
"optional": true
|
|
73
|
+
},
|
|
74
|
+
"pg": {
|
|
75
|
+
"optional": true
|
|
76
|
+
},
|
|
77
|
+
"socket.io": {
|
|
78
|
+
"optional": true
|
|
79
|
+
},
|
|
80
|
+
"socket.io-client": {
|
|
81
|
+
"optional": true
|
|
82
|
+
},
|
|
83
|
+
"otplib": {
|
|
84
|
+
"optional": true
|
|
85
|
+
},
|
|
86
|
+
"qrcode": {
|
|
87
|
+
"optional": true
|
|
65
88
|
}
|
|
66
89
|
},
|
|
67
90
|
"devDependencies": {
|
|
68
91
|
"@types/better-sqlite3": "^7.6.13",
|
|
69
92
|
"@types/node": "^20.14.2",
|
|
93
|
+
"@types/qrcode": "^1.5.6",
|
|
70
94
|
"@vitest/coverage-v8": "^4.0.18",
|
|
95
|
+
"otplib": "^12.0.1",
|
|
96
|
+
"qrcode": "^1.5.4",
|
|
71
97
|
"typescript": "^5.4.5",
|
|
72
98
|
"vitest": "^4.0.18"
|
|
73
99
|
},
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export function GET({ params }: { params: { id: string } }) {
|
|
2
|
-
return Response.json({
|
|
3
|
-
id: params.id,
|
|
4
|
-
username: 'sarah_dev',
|
|
5
|
-
display_name: 'Sarah Chen',
|
|
6
|
-
content: 'Sample post content',
|
|
7
|
-
likes: 42,
|
|
8
|
-
replies: [],
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function DELETE({ params }: { params: { id: string } }) {
|
|
13
|
-
return Response.json({ ok: true, deleted: params.id });
|
|
14
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export function GET() {
|
|
2
|
-
return Response.json([
|
|
3
|
-
{ id: 1, username: 'sarah_dev', display_name: 'Sarah Chen', content: 'Just shipped a new feature using LumenJS!', likes: 42, replies: 5, shares: 12 },
|
|
4
|
-
{ id: 2, username: 'alex_design', display_name: 'Alex Rivera', content: 'Working on a new design system.', likes: 38, replies: 3, shares: 8 },
|
|
5
|
-
{ id: 3, username: 'emma_data', display_name: 'Emma Williams', content: 'Trained a new model on customer feedback data.', likes: 67, replies: 8, shares: 21 },
|
|
6
|
-
]);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function POST() {
|
|
10
|
-
return Response.json({ ok: true, message: 'Post created (mock)' });
|
|
11
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import crypto from 'crypto';
|
|
2
|
-
import { compress } from '../lib/media.js';
|
|
3
|
-
|
|
4
|
-
export async function POST(req: any) {
|
|
5
|
-
const file = req.files?.[0];
|
|
6
|
-
if (!file) throw { status: 400, message: 'No file provided' };
|
|
7
|
-
if (!req.storage) throw { status: 503, message: 'Storage not configured' };
|
|
8
|
-
|
|
9
|
-
const { data, mimeType, ext } = await compress(file.data, file.contentType);
|
|
10
|
-
const key = `uploads/${crypto.randomUUID()}${ext}`;
|
|
11
|
-
|
|
12
|
-
const stored = await req.storage.put(data, {
|
|
13
|
-
key,
|
|
14
|
-
mimeType,
|
|
15
|
-
fileName: file.fileName,
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
return { url: stored.url, key: stored.key };
|
|
19
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
CREATE TABLE IF NOT EXISTS users (
|
|
2
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
3
|
-
username TEXT NOT NULL UNIQUE,
|
|
4
|
-
display_name TEXT NOT NULL,
|
|
5
|
-
avatar_url TEXT NOT NULL DEFAULT '',
|
|
6
|
-
bio TEXT NOT NULL DEFAULT '',
|
|
7
|
-
cover_url TEXT NOT NULL DEFAULT '',
|
|
8
|
-
followers_count INTEGER NOT NULL DEFAULT 0,
|
|
9
|
-
following_count INTEGER NOT NULL DEFAULT 0,
|
|
10
|
-
created_at TEXT NOT NULL DEFAULT (date('now'))
|
|
11
|
-
);
|
|
12
|
-
|
|
13
|
-
CREATE TABLE IF NOT EXISTS posts (
|
|
14
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
15
|
-
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
16
|
-
content TEXT NOT NULL,
|
|
17
|
-
parent_id INTEGER REFERENCES posts(id),
|
|
18
|
-
likes_count INTEGER NOT NULL DEFAULT 0,
|
|
19
|
-
replies_count INTEGER NOT NULL DEFAULT 0,
|
|
20
|
-
shares_count INTEGER NOT NULL DEFAULT 0,
|
|
21
|
-
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
CREATE TABLE IF NOT EXISTS notifications (
|
|
25
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
26
|
-
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
27
|
-
type TEXT NOT NULL,
|
|
28
|
-
actor_id INTEGER NOT NULL REFERENCES users(id),
|
|
29
|
-
post_id INTEGER REFERENCES posts(id),
|
|
30
|
-
read INTEGER NOT NULL DEFAULT 0,
|
|
31
|
-
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
CREATE TABLE IF NOT EXISTS trending (
|
|
35
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
36
|
-
hashtag TEXT NOT NULL UNIQUE,
|
|
37
|
-
post_count INTEGER NOT NULL DEFAULT 0
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
-- Seed users
|
|
41
|
-
INSERT INTO users (username, display_name, avatar_url, bio, followers_count, following_count, created_at) VALUES
|
|
42
|
-
('sarah_dev', 'Sarah Chen', '🧑💻', 'Full-stack developer. Open source enthusiast. Building the future one commit at a time.', 1240, 385, '2024-06-15'),
|
|
43
|
-
('alex_design', 'Alex Rivera', '🎨', 'UI/UX designer at heart. Pixels matter. Currently exploring design systems.', 890, 210, '2024-08-20'),
|
|
44
|
-
('mike_ops', 'Mike Johnson', '🛠️', 'DevOps engineer. Infrastructure as code. Coffee as fuel.', 560, 420, '2024-09-10'),
|
|
45
|
-
('emma_data', 'Emma Williams', '📊', 'Data scientist. ML enthusiast. Turning data into insights.', 2100, 150, '2024-03-05');
|
|
46
|
-
|
|
47
|
-
-- Seed posts
|
|
48
|
-
INSERT INTO posts (user_id, content, likes_count, replies_count, shares_count, created_at) VALUES
|
|
49
|
-
(1, 'Just shipped a new feature using LumenJS! The file-based routing makes everything so clean. No more route config files! 🚀', 42, 5, 12, '2025-03-21 14:30:00'),
|
|
50
|
-
(2, 'Working on a new design system. The key insight: consistency beats creativity when building at scale. Every component should feel like it belongs.', 38, 3, 8, '2025-03-21 12:15:00'),
|
|
51
|
-
(4, 'Trained a new model on customer feedback data. Accuracy went from 78% to 94% just by cleaning the input data. Garbage in, garbage out is real. 📈', 67, 8, 21, '2025-03-21 10:00:00'),
|
|
52
|
-
(3, 'Migrated our entire CI/CD pipeline to GitHub Actions. 40% faster builds and way easier to maintain. Should have done this months ago.', 29, 4, 6, '2025-03-20 18:45:00'),
|
|
53
|
-
(1, 'Hot take: TypeScript''s type system is a programming language in itself. And I love it. 💙', 85, 12, 15, '2025-03-20 16:20:00'),
|
|
54
|
-
(2, 'New blog post: "Why your loading states are making users anxious" — skeleton screens vs spinners vs progress bars. Link in bio!', 51, 7, 19, '2025-03-20 11:30:00'),
|
|
55
|
-
(4, 'PSA: If you''re using pandas, try polars. It''s not just faster — the API is actually more intuitive once you get used to it.', 93, 15, 34, '2025-03-19 20:00:00'),
|
|
56
|
-
(3, 'Docker tip: multi-stage builds reduced our image size from 1.2GB to 180MB. Always worth the extra 5 minutes of setup.', 44, 6, 11, '2025-03-19 15:30:00'),
|
|
57
|
-
(1, 'Weekend project: built a CLI tool that generates commit messages from diffs using Claude. It''s surprisingly good at understanding context.', 112, 18, 28, '2025-03-18 09:15:00'),
|
|
58
|
-
(2, 'The best design feedback I ever got: "Can my grandma use this?" Simple but powerful heuristic. 👵', 76, 9, 22, '2025-03-17 14:00:00');
|
|
59
|
-
|
|
60
|
-
-- Seed replies (parent_id references)
|
|
61
|
-
INSERT INTO posts (user_id, content, parent_id, likes_count, created_at) VALUES
|
|
62
|
-
(2, 'Love the file-based routing approach! How does it handle dynamic params?', 1, 8, '2025-03-21 14:45:00'),
|
|
63
|
-
(3, 'Totally agree on TypeScript. The conditional types are mind-bending though 😅', 5, 12, '2025-03-20 16:35:00'),
|
|
64
|
-
(4, 'Multi-stage builds are a game changer. We use them everywhere now.', 8, 5, '2025-03-19 15:45:00');
|
|
65
|
-
|
|
66
|
-
-- Seed notifications (for user 1 - sarah_dev)
|
|
67
|
-
INSERT INTO notifications (user_id, type, actor_id, post_id, created_at) VALUES
|
|
68
|
-
(1, 'like', 2, 1, '2025-03-21 14:35:00'),
|
|
69
|
-
(1, 'reply', 2, 1, '2025-03-21 14:45:00'),
|
|
70
|
-
(1, 'follow', 3, NULL, '2025-03-21 13:00:00'),
|
|
71
|
-
(1, 'like', 4, 5, '2025-03-20 16:25:00'),
|
|
72
|
-
(1, 'reply', 3, 5, '2025-03-20 16:35:00');
|
|
73
|
-
|
|
74
|
-
-- Seed trending
|
|
75
|
-
INSERT INTO trending (hashtag, post_count) VALUES
|
|
76
|
-
('#WebComponents', 1250),
|
|
77
|
-
('#TypeScript', 3400),
|
|
78
|
-
('#DevOps', 890);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
ALTER TABLE posts ADD COLUMN image_url TEXT NOT NULL DEFAULT '';
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
-- Add OAuth identity columns to users table
|
|
2
|
-
ALTER TABLE users ADD COLUMN oauth_provider TEXT;
|
|
3
|
-
ALTER TABLE users ADD COLUMN oauth_sub TEXT;
|
|
4
|
-
ALTER TABLE users ADD COLUMN email TEXT;
|
|
5
|
-
|
|
6
|
-
-- Prevent duplicate OAuth accounts
|
|
7
|
-
CREATE UNIQUE INDEX IF NOT EXISTS idx_users_oauth_sub ON users(oauth_provider, oauth_sub);
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# Social Template — Architecture
|
|
2
|
-
|
|
3
|
-
A social networking super app template for LumenJS, inspired by Twitter, LinkedIn, and dev.to.
|
|
4
|
-
|
|
5
|
-
**Demo**: https://social.lumenjs.dev
|
|
6
|
-
|
|
7
|
-
## Tech Stack
|
|
8
|
-
|
|
9
|
-
- **LumenJS** — file-based routing, SSR with Lit SSR, server loaders, API routes
|
|
10
|
-
- **Lit** — web components with Shadow DOM, reactive properties, CSS-in-JS
|
|
11
|
-
- **SQLite** — mock data via migrations (seeded on first run)
|
|
12
|
-
- **No frameworks** — pure Lit + native HTML elements, no Tailwind, no NuralyUI
|
|
13
|
-
|
|
14
|
-
## Directory Structure
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
templates/social/
|
|
18
|
-
├── lumenjs.config.ts # App config (title only)
|
|
19
|
-
├── package.json # Template metadata
|
|
20
|
-
├── data/
|
|
21
|
-
│ └── migrations/
|
|
22
|
-
│ └── 001_init.sql # DB schema + seed data
|
|
23
|
-
├── api/
|
|
24
|
-
│ ├── posts.ts # GET /api/posts, POST /api/posts
|
|
25
|
-
│ ├── posts/[id].ts # GET /api/posts/:id, DELETE
|
|
26
|
-
│ └── profile/[username].ts # GET /api/profile/:username
|
|
27
|
-
├── pages/
|
|
28
|
-
│ ├── _layout.ts # App shell (sidebar, right panel, mobile nav, theming)
|
|
29
|
-
│ ├── index.ts # Feed with stories bar + widget cards
|
|
30
|
-
│ ├── explore.ts # Tags, suggested users, top posts
|
|
31
|
-
│ ├── notifications.ts # Notification list with type icons
|
|
32
|
-
│ ├── messages.ts # Conversations + chat detail
|
|
33
|
-
│ ├── bookmarks.ts # Saved posts list
|
|
34
|
-
│ ├── settings.ts # Settings with dark mode toggle
|
|
35
|
-
│ ├── new.ts # New post composer
|
|
36
|
-
│ ├── post/
|
|
37
|
-
│ │ └── [id].ts # Post detail with comments
|
|
38
|
-
│ ├── profile/
|
|
39
|
-
│ │ └── [username].ts # User profile with posts
|
|
40
|
-
│ └── apps/
|
|
41
|
-
│ ├── index.ts # App marketplace
|
|
42
|
-
│ └── [id].ts # Individual app view
|
|
43
|
-
└── docs/ # This documentation
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Pages & Routes
|
|
47
|
-
|
|
48
|
-
| Route | File | Description |
|
|
49
|
-
|-------|------|-------------|
|
|
50
|
-
| `/` | `pages/index.ts` | Feed with stories, posts, widget cards |
|
|
51
|
-
| `/explore` | `pages/explore.ts` | Tags, users, popular posts |
|
|
52
|
-
| `/notifications` | `pages/notifications.ts` | Activity notifications |
|
|
53
|
-
| `/messages` | `pages/messages.ts` | Chat conversations |
|
|
54
|
-
| `/bookmarks` | `pages/bookmarks.ts` | Saved posts |
|
|
55
|
-
| `/settings` | `pages/settings.ts` | Account & theme settings |
|
|
56
|
-
| `/new` | `pages/new.ts` | Create new post |
|
|
57
|
-
| `/post/:id` | `pages/post/[id].ts` | Single post with comments |
|
|
58
|
-
| `/profile/:username` | `pages/profile/[username].ts` | User profile |
|
|
59
|
-
| `/apps` | `pages/apps/index.ts` | App marketplace |
|
|
60
|
-
| `/apps/:id` | `pages/apps/[id].ts` | Individual app |
|
|
61
|
-
|
|
62
|
-
## Layout Architecture
|
|
63
|
-
|
|
64
|
-
`_layout.ts` is the root layout wrapping all pages via `<slot>`.
|
|
65
|
-
|
|
66
|
-
**Desktop** (>860px): icon sidebar (68px) + main content (600px max) + right sidebar (350px)
|
|
67
|
-
**Tablet** (640-860px): sidebar + main content (right sidebar hidden)
|
|
68
|
-
**Mobile** (<640px): mobile top bar + full-width content + bottom nav bar + more menu sheet
|
|
69
|
-
|
|
70
|
-
## Theming
|
|
71
|
-
|
|
72
|
-
Dark mode via CSS custom properties set on `document.documentElement`. Toggle in settings persists to `localStorage('theme')`. See `docs/theming.md`.
|
|
73
|
-
|
|
74
|
-
## Data
|
|
75
|
-
|
|
76
|
-
All data is mock — hardcoded in loaders and API handlers. SQLite migration seeds initial data. See `docs/data.md`.
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
# Shared Patterns & Components
|
|
2
|
-
|
|
3
|
-
## SVG Icon Library
|
|
4
|
-
|
|
5
|
-
All icons are inline SVG in Lit `html` tagged templates. Style: feather icons (stroke, no fill, 1.5 stroke-width, 22x22 default).
|
|
6
|
-
|
|
7
|
-
### Layout icons (`_layout.ts`)
|
|
8
|
-
- `home` — house with chimney
|
|
9
|
-
- `explore` — magnifying glass (search)
|
|
10
|
-
- `bell` — notification bell
|
|
11
|
-
- `message` — envelope
|
|
12
|
-
- `user` — person silhouette
|
|
13
|
-
- `search` — small magnifying glass (16x16)
|
|
14
|
-
- `post` — pen/edit
|
|
15
|
-
- `bookmark` — bookmark flag
|
|
16
|
-
- `plus` — plus sign (24x24, 2 stroke-width)
|
|
17
|
-
- `settings` — gear/cog
|
|
18
|
-
|
|
19
|
-
### Feed icons (`index.ts`)
|
|
20
|
-
- `comment` — chat bubble (17x17)
|
|
21
|
-
- `repost` — circular arrows (17x17)
|
|
22
|
-
- `heart` — heart outline (17x17)
|
|
23
|
-
- `share` — upload/share arrow (17x17)
|
|
24
|
-
|
|
25
|
-
### Post detail icons (`post/[id].ts`)
|
|
26
|
-
- `heart`, `comment`, `bookmark` — 18x18 variants
|
|
27
|
-
|
|
28
|
-
### Profile icon (`profile/[username].ts`)
|
|
29
|
-
- `location` — map pin (14x14)
|
|
30
|
-
- `briefcase` — work bag (14x14)
|
|
31
|
-
- `calendar` — calendar grid (14x14)
|
|
32
|
-
- Follow button: user-plus (18x18, 2 stroke-width)
|
|
33
|
-
|
|
34
|
-
### Messages icons (`messages.ts`)
|
|
35
|
-
- `send`, `image`, `smile`, `check`, `checkDouble`, `phone`, `video`, `info`, `attach`, `mic`, `search`
|
|
36
|
-
|
|
37
|
-
### Notifications icons (`notifications.ts`)
|
|
38
|
-
- `heart` — filled red (#e53935)
|
|
39
|
-
- `comment` — filled blue (#3b49df)
|
|
40
|
-
- `userPlus` — stroke green (#22c55e)
|
|
41
|
-
|
|
42
|
-
### New post icons (`new.ts`)
|
|
43
|
-
- `image`, `video`, `smile`, `mapPin`, `globe`, `close`
|
|
44
|
-
|
|
45
|
-
### Settings icons (`settings.ts`)
|
|
46
|
-
- `user`, `lock`, `bell`, `eye`, `palette`, `globe`, `shield`, `help`, `logout`, `chevron`
|
|
47
|
-
|
|
48
|
-
## Post Card Pattern
|
|
49
|
-
|
|
50
|
-
Used in feed, profile, and bookmarks:
|
|
51
|
-
```
|
|
52
|
-
<a class="post" href="/post/${id}">
|
|
53
|
-
<div class="post-avatar" style="background:${color}">
|
|
54
|
-
${avatar ? <img> : initials}
|
|
55
|
-
</div>
|
|
56
|
-
<div class="post-body">
|
|
57
|
-
<div class="post-header">name + @handle + · + time</div>
|
|
58
|
-
<div class="post-content">text (3-line clamp)</div>
|
|
59
|
-
<div class="post-media">image or video (16:9)</div>
|
|
60
|
-
<div class="post-actions">comment + repost + heart + share</div>
|
|
61
|
-
</div>
|
|
62
|
-
</a>
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Widget Card Pattern
|
|
66
|
-
|
|
67
|
-
Used for poll, event, job in feed:
|
|
68
|
-
```
|
|
69
|
-
<div class="widget-card">
|
|
70
|
-
<div class="widget-header">
|
|
71
|
-
avatar + name + time + badge (Poll/Event/Job)
|
|
72
|
-
</div>
|
|
73
|
-
<div class="...">custom widget body</div>
|
|
74
|
-
</div>
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## Story Thumbnail
|
|
78
|
-
|
|
79
|
-
```
|
|
80
|
-
<div class="story">
|
|
81
|
-
<div class="story-ring">
|
|
82
|
-
<div class="story-avatar-wrap">
|
|
83
|
-
<div class="story-avatar"><img></div>
|
|
84
|
-
(optional: story-plus for "You")
|
|
85
|
-
</div>
|
|
86
|
-
</div>
|
|
87
|
-
<span class="story-name">Name</span>
|
|
88
|
-
</div>
|
|
89
|
-
```
|
|
90
|
-
56x80px rounded rectangles with border. Click opens full-screen viewer.
|
|
91
|
-
|
|
92
|
-
## Mobile Patterns
|
|
93
|
-
|
|
94
|
-
**Bottom bar**: 5 items — Home, Explore, + (purple FAB), Messages, More (three dots)
|
|
95
|
-
|
|
96
|
-
**More menu**: overlay + bottom sheet with drag handle + menu items (Profile, Bookmarks, Apps, Notifications, Settings)
|
|
97
|
-
|
|
98
|
-
**Mobile top bar**: avatar + "Home" text (link to /) + spacer + settings gear + bell + message icons
|
|
99
|
-
|
|
100
|
-
**Message mobile**: click conversation → `_showChat` state toggles `.chat-open` class → hides list, shows full-screen chat with back arrow
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
# Mock Data & API Routes
|
|
2
|
-
|
|
3
|
-
## Mock Users
|
|
4
|
-
|
|
5
|
-
| Username | Display Name | Initials | Color | Avatar |
|
|
6
|
-
|----------|-------------|----------|-------|--------|
|
|
7
|
-
| `aymen` | Aymen Labidi | AL | `#7c3aed` | GitHub avatar (u/3775924) |
|
|
8
|
-
| `alex_design` | Alex Rivera | AR | `#e44d26` | Initials |
|
|
9
|
-
| `emma_data` | Emma Williams | EW | `#3572a5` | Initials |
|
|
10
|
-
| `mike_ops` | Mike Johnson | MJ | `#22c55e` | Initials |
|
|
11
|
-
| `lisa_pm` | Lisa Park | LP | `#a855f7` | Initials |
|
|
12
|
-
| `tom_arch` | Tom Brooks | TB | `#ef4444` | Initials |
|
|
13
|
-
| `nina_sec` | Nina Patel | NP | `#f59e0b` | Initials |
|
|
14
|
-
|
|
15
|
-
"aymen" is the current user (shown in compose avatars, sidebar, settings).
|
|
16
|
-
|
|
17
|
-
## Mock Posts (Feed)
|
|
18
|
-
|
|
19
|
-
6 posts in `index.ts` loader with IDs 1-6. Posts 1, 3 have images, post 4 has video, post 6 has image. Content is long (multi-line, triggers "See more" on post 1).
|
|
20
|
-
|
|
21
|
-
## Stories
|
|
22
|
-
|
|
23
|
-
7 stories in `index.ts` loader. Each has an Unsplash image (400x700 crop) and caption. Displayed as rectangular thumbnails.
|
|
24
|
-
|
|
25
|
-
## Feed Widgets
|
|
26
|
-
|
|
27
|
-
3 widgets inserted between posts by `position`:
|
|
28
|
-
- **Poll** (pos 2): "What framework do you use most in 2025?" — React 45%, LumenJS 35%, Vue 15%, Other 5% (142 votes)
|
|
29
|
-
- **Event** (pos 4): "DevOps Meetup 2025" — Apr 5, 2025, Online/Zoom, 48 attending
|
|
30
|
-
- **Job** (pos 6): DataFlow, Senior ML Engineer, Remote, $150k-$200k
|
|
31
|
-
|
|
32
|
-
## Post Detail Data
|
|
33
|
-
|
|
34
|
-
`post/[id].ts` has 6 posts (IDs 1-6) with full content, tags, dates, read times. Posts 1 and 5 have comment threads.
|
|
35
|
-
|
|
36
|
-
## Messages Data
|
|
37
|
-
|
|
38
|
-
5 conversations in `messages.ts` with full chat histories:
|
|
39
|
-
1. Alex Rivera — LumenJS discussion (9 messages, 2 unread)
|
|
40
|
-
2. Emma Williams — polars benchmarks (6 messages)
|
|
41
|
-
3. Mike Johnson — CI pipeline (5 messages)
|
|
42
|
-
4. Lisa Park — roadmap sync (3 messages, 1 unread)
|
|
43
|
-
5. Tom Brooks — architecture diagram (2 messages)
|
|
44
|
-
|
|
45
|
-
## Notifications
|
|
46
|
-
|
|
47
|
-
5 notifications for user "aymen": 2 likes, 2 comments, 1 follow.
|
|
48
|
-
|
|
49
|
-
## Apps Marketplace
|
|
50
|
-
|
|
51
|
-
12 apps with categories:
|
|
52
|
-
- Productivity: Calendar, Notes, Timer, Task Board
|
|
53
|
-
- Social: Poll Creator
|
|
54
|
-
- Entertainment: Weather, News Feed
|
|
55
|
-
- Finance: Stock Tracker, Budget Tracker
|
|
56
|
-
- Developer Tools: Translator, Code Snippets
|
|
57
|
-
- Health: Step Counter
|
|
58
|
-
|
|
59
|
-
3 apps have real UI: poll (form), calendar (grid), notes (list).
|
|
60
|
-
|
|
61
|
-
## Database Schema (`001_init.sql`)
|
|
62
|
-
|
|
63
|
-
```sql
|
|
64
|
-
users (id, username, display_name, avatar_url, bio, cover_url, followers_count, following_count, created_at)
|
|
65
|
-
posts (id, user_id, content, parent_id, likes_count, replies_count, shares_count, created_at)
|
|
66
|
-
notifications (id, user_id, type, actor_id, post_id, read, created_at)
|
|
67
|
-
trending (id, hashtag, post_count)
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
Seeded with 4 users, 10 posts + 3 replies, 5 notifications, 3 trending tags.
|
|
71
|
-
|
|
72
|
-
## API Routes
|
|
73
|
-
|
|
74
|
-
| Method | Route | Response |
|
|
75
|
-
|--------|-------|----------|
|
|
76
|
-
| GET | `/api/posts` | Array of posts (id, username, display_name, content, likes, replies, shares) |
|
|
77
|
-
| POST | `/api/posts` | `{ ok: true, message: "Post created (mock)" }` |
|
|
78
|
-
| GET | `/api/posts/:id` | Single post with replies array |
|
|
79
|
-
| DELETE | `/api/posts/:id` | `{ ok: true, deleted: id }` |
|
|
80
|
-
| GET | `/api/profile/:username` | User profile with posts array |
|
|
81
|
-
|
|
82
|
-
All API routes return hardcoded mock data — not connected to SQLite. The migration exists for future use when persistence is implemented.
|
|
83
|
-
|
|
84
|
-
## Adding New Mock Data
|
|
85
|
-
|
|
86
|
-
1. Add to the `loader()` function in the relevant page file
|
|
87
|
-
2. For new users: add to the `USERS` object in profile and post detail pages
|
|
88
|
-
3. For new posts: add to both `index.ts` (feed) and `post/[id].ts` (detail) loaders
|
|
89
|
-
4. For new apps: add to `apps/index.ts` loader + `APPS` object in `apps/[id].ts`
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
# Pages Reference
|
|
2
|
-
|
|
3
|
-
## `_layout.ts` — App Shell
|
|
4
|
-
|
|
5
|
-
Root layout wrapping all pages.
|
|
6
|
-
|
|
7
|
-
**Desktop**: icon sidebar | main `<slot>` | right sidebar (weather, calendar, quick apps, trending)
|
|
8
|
-
**Mobile**: top bar (avatar + "Home" + icons) | content | bottom nav (home, explore, +post, messages, more)
|
|
9
|
-
|
|
10
|
-
Features:
|
|
11
|
-
- Sidebar nav: Home, Explore, Notifications, Messages, Bookmarks, Apps, Profile, Settings
|
|
12
|
-
- Right sidebar widgets: weather (Tunisia 24°), calendar (3 events), quick apps (4 icons), trending tags
|
|
13
|
-
- Mobile "more" bottom sheet: Profile, Bookmarks, Apps, Notifications, Settings
|
|
14
|
-
- Dark mode theming via CSS custom properties
|
|
15
|
-
- Viewport meta override (no zoom on mobile)
|
|
16
|
-
|
|
17
|
-
## `index.ts` — Feed (`/`)
|
|
18
|
-
|
|
19
|
-
**Stories bar**: horizontal scrollable thumbnails (56x80px, rounded rect), "You" has + icon, images from Unsplash. Click opens full-screen story viewer with progress bars, auto-advance (5s), tap left/right to navigate.
|
|
20
|
-
|
|
21
|
-
**Widget cards** mixed between posts:
|
|
22
|
-
- **Poll** (position 2): question + 4 options with percentage bars + vote count
|
|
23
|
-
- **Event** (position 4): title, date, location, attendees, "Interested" button
|
|
24
|
-
- **Job** (position 6): company, role, location, salary, "Apply" button
|
|
25
|
-
|
|
26
|
-
**Post cards**: avatar (image for aymen, initials for others) + name + @handle + time + content (3-line clamp, "See more" on first post) + media (image/video, 16:9 aspect ratio) + action bar (comment, repost, heart, share with SVG icons)
|
|
27
|
-
|
|
28
|
-
Loader returns: `{ stories[], widgets[], posts[] }`
|
|
29
|
-
|
|
30
|
-
## `post/[id].ts` — Post Detail (`/post/:id`)
|
|
31
|
-
|
|
32
|
-
Full article view with larger text. Shows media (full-width, no padding). Tags, author meta, date + read time.
|
|
33
|
-
|
|
34
|
-
Action bar: heart, comment, bookmark (SVG). Comment input below. Replies rendered as cards with avatar + name + content.
|
|
35
|
-
|
|
36
|
-
6 mock posts with IDs 1-6. Posts 1, 3, 4, 6 have media.
|
|
37
|
-
|
|
38
|
-
## `profile/[username].ts` — Profile (`/profile/:username`)
|
|
39
|
-
|
|
40
|
-
No banner. Avatar + name + bio on same row, follow button (SVG user-plus icon) top-right.
|
|
41
|
-
|
|
42
|
-
Meta: location (pin icon), work (briefcase icon), joined date (calendar icon).
|
|
43
|
-
|
|
44
|
-
Posts list below. 4 mock users: aymen, alex_design, mike_ops, emma_data.
|
|
45
|
-
|
|
46
|
-
Aymen uses GitHub avatar image, others use letter initials with brand colors.
|
|
47
|
-
|
|
48
|
-
## `explore.ts` — Explore (`/explore`)
|
|
49
|
-
|
|
50
|
-
Tag cards grid (colored top bar per tag), 8 tags. Top posts section with title links.
|
|
51
|
-
|
|
52
|
-
## `notifications.ts` — Notifications (`/notifications`)
|
|
53
|
-
|
|
54
|
-
List with avatar + type icon badge (heart=red, comment=blue, follow=green). 5 mock notifications.
|
|
55
|
-
|
|
56
|
-
## `messages.ts` — Messages (`/messages`)
|
|
57
|
-
|
|
58
|
-
Split view: conversation list (340px) + chat panel. Click conversation to switch. 5 conversations with full message histories.
|
|
59
|
-
|
|
60
|
-
Chat features: message bubbles (purple=me, gray=them), small avatar on their messages, date separators, read receipts (single check=sent, double purple check=read), online indicators (green dot).
|
|
61
|
-
|
|
62
|
-
Input: attach, image, emoji, mic buttons + text input + send button.
|
|
63
|
-
|
|
64
|
-
Mobile: click conversation → full-screen chat with back arrow.
|
|
65
|
-
|
|
66
|
-
## `bookmarks.ts` — Bookmarks (`/bookmarks`)
|
|
67
|
-
|
|
68
|
-
Simple list with bookmark icon + title + author + saved time. 3 mock bookmarks.
|
|
69
|
-
|
|
70
|
-
## `settings.ts` — Settings (`/settings`)
|
|
71
|
-
|
|
72
|
-
Profile card (avatar + name + email + edit button).
|
|
73
|
-
|
|
74
|
-
Sections:
|
|
75
|
-
- Account: account info, password, privacy (menu items with chevron)
|
|
76
|
-
- Preferences: dark mode (wired toggle), push notifications, email notifications, sound effects
|
|
77
|
-
- More: accessibility, language, help center, log out (red)
|
|
78
|
-
|
|
79
|
-
## `new.ts` — New Post (`/new`)
|
|
80
|
-
|
|
81
|
-
Compose screen: close button + post button in header. Avatar + textarea. Visibility line ("Everyone can reply"). Tool bar: image, video, emoji, location + char counter (0/500).
|
|
82
|
-
|
|
83
|
-
## `apps/index.ts` — App Marketplace (`/apps`)
|
|
84
|
-
|
|
85
|
-
Search bar, 3 featured cards, category filter buttons (All + 6 categories, active state), app list (icon + name + desc + category + "Open" button). 12 mock apps.
|
|
86
|
-
|
|
87
|
-
## `apps/[id].ts` — App Detail (`/apps/:id`)
|
|
88
|
-
|
|
89
|
-
Header: large icon + name + description + "Open" + "Add to sidebar" buttons.
|
|
90
|
-
|
|
91
|
-
Body: 3 apps have real UI:
|
|
92
|
-
- **poll**: question input + option inputs + add option + settings
|
|
93
|
-
- **calendar**: March 2025 grid with today highlighted + nav arrows
|
|
94
|
-
- **notes**: note list with title/preview/date + new note button
|
|
95
|
-
|
|
96
|
-
Other apps show placeholder.
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
# Theming & Dark Mode
|
|
2
|
-
|
|
3
|
-
## How It Works
|
|
4
|
-
|
|
5
|
-
1. `_layout.ts` defines two theme objects: `THEME_LIGHT` and `THEME_DARK`
|
|
6
|
-
2. `applyTheme(dark)` sets CSS custom properties on `document.documentElement`
|
|
7
|
-
3. On page load, reads `localStorage.getItem('theme')` and applies immediately
|
|
8
|
-
4. `window.__nk_toggle_theme(dark)` exposed for the settings page to call
|
|
9
|
-
5. All pages use `var(--xxx)` instead of hardcoded colors
|
|
10
|
-
|
|
11
|
-
## CSS Custom Properties
|
|
12
|
-
|
|
13
|
-
| Variable | Light | Dark | Usage |
|
|
14
|
-
|----------|-------|------|-------|
|
|
15
|
-
| `--bg` | `#fff` | `#15202b` | Page/card backgrounds |
|
|
16
|
-
| `--bg-secondary` | `#f7f9f9` | `#1e2d3d` | Sidebar cards, secondary panels |
|
|
17
|
-
| `--bg-hover` | `#fafafa` | `#1c2b3a` | Hover states |
|
|
18
|
-
| `--border` | `#eff3f4` | `#38444d` | Primary borders |
|
|
19
|
-
| `--border-light` | `#f0f0f0` | `#2f3b44` | Subtle dividers |
|
|
20
|
-
| `--text` | `#0f1419` | `#e7e9ea` | Primary text |
|
|
21
|
-
| `--text-secondary` | `#536471` | `#8b98a5` | Secondary text, handles |
|
|
22
|
-
| `--text-tertiary` | `#a3a3a3` | `#6e767d` | Timestamps, counts |
|
|
23
|
-
| `--accent` | `#7c3aed` | `#8b5cf6` | Purple accent (buttons, links) |
|
|
24
|
-
| `--accent-hover` | `#6d28d9` | `#7c3aed` | Accent hover state |
|
|
25
|
-
| `--input-bg` | `#eff3f4` | `#253341` | Input/search backgrounds |
|
|
26
|
-
| `--card-bg` | `#f7f9f9` | `#1e2d3d` | Card backgrounds |
|
|
27
|
-
| `--overlay` | `rgba(0,0,0,0.4)` | `rgba(0,0,0,0.7)` | Modal overlays |
|
|
28
|
-
| `--backdrop` | `rgba(255,255,255,0.85)` | `rgba(21,32,43,0.85)` | Glassmorphism headers |
|
|
29
|
-
|
|
30
|
-
## Persistence
|
|
31
|
-
|
|
32
|
-
- Key: `localStorage.getItem('theme')`
|
|
33
|
-
- Values: `'light'` (default) or `'dark'`
|
|
34
|
-
- Applied before first render (runs at module scope in `_layout.ts`)
|
|
35
|
-
|
|
36
|
-
## Settings Toggle
|
|
37
|
-
|
|
38
|
-
In `pages/settings.ts`, the dark mode checkbox:
|
|
39
|
-
```typescript
|
|
40
|
-
<input type="checkbox"
|
|
41
|
-
.checked=${this._dark}
|
|
42
|
-
@change=${(e) => {
|
|
43
|
-
this._dark = e.target.checked;
|
|
44
|
-
window.__nk_toggle_theme?.(this._dark);
|
|
45
|
-
}}>
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## Colors That Stay Fixed (Not Themed)
|
|
49
|
-
|
|
50
|
-
Avatar brand colors are per-user and don't change with theme:
|
|
51
|
-
- `#e44d26` (Alex), `#3572a5` (Emma), `#22c55e` (Mike), `#a855f7` (Lisa), `#ef4444` (Tom), `#f59e0b` (Nina)
|
|
52
|
-
- White text on colored backgrounds (`color: #fff`) stays white in both themes
|