diff --git a/AGENTS.md b/AGENTS.md
index eac4bbd..9bf8de2 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -13,7 +13,7 @@ This application uses Cloudflare Developer Platform, including Workers and Durab
- TypeScript strict mode
- Single quotes, trailing comma
-- Use prettier for formatting after each prompt
+- Run `npm run format` to format the code after each prompt
## Script rules
@@ -22,4 +22,10 @@ This application uses Cloudflare Developer Platform, including Workers and Durab
## Worker implementation
-- Internal worker routes all start with ${usersPath}, make sure to always prefix them
+- Internal worker routes all start with `${usersPath}`, make sure to always prefix them
+- Never override `.env` and `.dev.vars` files
+
+## API
+
+- All non-admin API paths start with `/${usersPath}/api/`
+- All admin API paths start with `/${usersPath}/admin/api/`
diff --git a/public/users/admin/index.html b/public/users/admin/index.html
new file mode 100644
index 0000000..27f1731
--- /dev/null
+++ b/public/users/admin/index.html
@@ -0,0 +1,729 @@
+
+
+
+
+
+ Admin Dashboard
+
+
+
+
+
+
+
+
+ StartupAPI Admin
+
+
+ Users
+
+
+
+
+ ID
+ Name
+ Email
+ Provider
+ Created
+ Actions
+
+
+
+
+
+
+
+
+
+
+
Accounts
+ Create Account
+
+
+
+
+
+ ID
+ Name
+ Status
+ Plan
+ Members
+ Created
+ Actions
+
+
+
+
+
+
+
+
+
+
+
+
+ Edit User
+
+
+ Name
+
+
+
+ Email
+
+
+
+ Cancel
+ Save
+
+
+
+
+
+ User Memberships
+
+
+
+
+ Account
+ Role
+ Current
+ Actions
+
+
+
+
+
+
+
+ Close
+
+
+
+
+
+ Edit Account
+
+
+ Name
+
+
+
+ Status
+
+ Active
+ Suspended
+ Canceled
+
+
+
+ Plan
+
+ Free
+ Pro
+ Enterprise
+
+
+
+ Cancel
+ Save
+
+
+
+
+
+ Create New Account
+
+ Account Name
+
+
+
+ Initial Owner (Optional)
+
+ -- No Owner --
+
+
+
+
+ Initial Plan
+
+ Free
+ Pro
+ Enterprise
+
+
+
+ Cancel
+ Create
+
+
+
+
+
+ Manage Members
+
+
+
+
Add Member
+
+
+ -- Select User --
+
+
+ User
+ Admin
+
+ Add
+
+
+
+ Current Members
+
+
+
+ User
+ Role
+ Joined
+ Actions
+
+
+
+
+
+
+
+
+ Close
+
+
+
+
+
+
diff --git a/public/users/power-strip.js b/public/users/power-strip.js
index 8519ea4..d349510 100644
--- a/public/users/power-strip.js
+++ b/public/users/power-strip.js
@@ -34,13 +34,17 @@ class PowerStrip extends HTMLElement {
async fetchUser() {
try {
- const res = await fetch(`${this.basePath}/me`);
+ const res = await fetch(`${this.basePath}/api/me`);
if (res.ok) {
const data = await res.json();
if (data.valid) {
- this.user = data.profile;
+ this.user = {
+ profile: data.profile,
+ is_admin: data.is_admin,
+ is_impersonated: data.is_impersonated,
+ };
// Fetch accounts if logged in
- const accountsRes = await fetch(`${this.basePath}/me/accounts`);
+ const accountsRes = await fetch(`${this.basePath}/api/me/accounts`);
if (accountsRes.ok) {
this.accounts = await accountsRes.json();
}
@@ -53,7 +57,7 @@ class PowerStrip extends HTMLElement {
async switchAccount(accountId) {
try {
- const res = await fetch(`${this.basePath}/me/accounts/switch`, {
+ const res = await fetch(`${this.basePath}/api/me/accounts/switch`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -122,22 +126,40 @@ class PowerStrip extends HTMLElement {
if (providers.length > 0 && providers[0] !== '') {
if (this.user) {
- const providerIcon = this.getProviderIcon(this.user.provider);
- const currentAccount = this.accounts.find(a => a.is_current) || (this.accounts.length > 0 ? this.accounts[0] : null);
- const accountName = currentAccount ? currentAccount.name : 'No Account';
-
+ const providerIcon = this.getProviderIcon(this.user.profile.provider);
+ const currentAccount = this.accounts.find((a) => a.is_current) || (this.accounts.length > 0 ? this.accounts[0] : null);
+ const accountName = currentAccount ? (currentAccount.personal ? this.user.profile.name : currentAccount.name) : 'No Account';
+
let switchButton = '';
+ let accountContainer = '';
+
if (this.accounts.length > 1) {
- switchButton = `Switch `;
-
- const accountList = this.accounts.map(acc => `
+ switchButton = `
+
+
+
+
+ `;
+
+ accountContainer = `
+
+ ${accountName}
+ ${switchButton}
+
+ `;
+
+ const accountList = this.accounts
+ .map(
+ (acc) => `
${acc.name}
${acc.is_current ? 'Current ' : ''}
- `).join('');
+ `,
+ )
+ .join('');
- accountSwitcher = `
+ accountSwitcher = `