diff --git a/App.uvue b/App.uvue
index c5aa6b1..560a7d7 100644
--- a/App.uvue
+++ b/App.uvue
@@ -1,5 +1,7 @@
diff --git a/packages/account/services/auth.uts b/packages/account/services/auth.uts
new file mode 100644
index 0000000..2005850
--- /dev/null
+++ b/packages/account/services/auth.uts
@@ -0,0 +1,35 @@
+import { API_BASE_URL, wait, requestJson } from '@/services/api.uts'
+export { API_BASE_URL, saveSession } from '@/services/api.uts'
+
+export async function requestSmsCode(phone: string): Promise {
+ if (API_BASE_URL.length == 0) {
+ await wait(350)
+ return phone.length == 11
+ }
+ await requestJson('/auth/sms-code', 'POST', { phone })
+ return true
+}
+
+export async function loginWithSms(phone: string, code: string): Promise {
+ if (API_BASE_URL.length == 0) {
+ await wait(300)
+ if (code.length != 6) throw new Error('验证码应为 6 位数字')
+ return 'demo-sms-token'
+ }
+ const result = await requestJson('/auth/sms-login', 'POST', { phone, code })
+ const token = result['token'] as string | null
+ if (token == null || token.length == 0) throw new Error('登录响应缺少 token')
+ return token
+}
+
+export async function loginWithPassword(phone: string, password: string): Promise {
+ if (API_BASE_URL.length == 0) {
+ await wait(300)
+ return 'demo-password-token'
+ }
+ const result = await requestJson('/auth/password-login', 'POST', { phone, password })
+ const token = result['token'] as string | null
+ if (token == null || token.length == 0) throw new Error('登录响应缺少 token')
+ return token
+}
+
diff --git a/packages/account/static/quick-login.svg b/packages/account/static/quick-login.svg
new file mode 100644
index 0000000..40ba4ef
--- /dev/null
+++ b/packages/account/static/quick-login.svg
@@ -0,0 +1,4 @@
+
diff --git a/static/mobile/images/shield.png b/packages/account/static/shield.png
similarity index 100%
rename from static/mobile/images/shield.png
rename to packages/account/static/shield.png
diff --git a/packages/account/static/wechat.svg b/packages/account/static/wechat.svg
new file mode 100644
index 0000000..1ec3c9c
--- /dev/null
+++ b/packages/account/static/wechat.svg
@@ -0,0 +1,8 @@
+
diff --git a/pages/article/article.uvue b/packages/content/article/article.uvue
similarity index 94%
rename from pages/article/article.uvue
rename to packages/content/article/article.uvue
index daec7fa..662c4cf 100644
--- a/pages/article/article.uvue
+++ b/packages/content/article/article.uvue
@@ -17,7 +17,7 @@