Skip to content

Commit 5daa81a

Browse files
committed
Initial Commit
0 parents  commit 5daa81a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+4935
-0
lines changed

.github/workflows/deploy.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Deploy to GitHub Pages
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
pages: write
11+
id-token: write
12+
13+
concurrency:
14+
group: "pages"
15+
cancel-in-progress: false
16+
17+
jobs:
18+
deploy:
19+
environment:
20+
name: github-pages
21+
url: ${{ steps.deployment.outputs.page_url }}
22+
runs-on: ubuntu-latest
23+
steps:
24+
- name: Checkout
25+
uses: actions/checkout@v4
26+
27+
- name: Setup Pages
28+
uses: actions/configure-pages@v5
29+
30+
- name: Inject Production Base Path
31+
# Swaps the local development base tag for the production subdirectory
32+
run: |
33+
sed -i 's|<base.*>|<base href="/axiom/">|g' index.html
34+
touch .nojekyll
35+
cp index.html 404.html
36+
37+
- name: Upload artifact
38+
uses: actions/upload-pages-artifact@v3
39+
with:
40+
# Zero-build project: The root directory IS the artifact
41+
path: '.'
42+
43+
- name: Deploy to GitHub Pages
44+
id: deployment
45+
uses: actions/deploy-pages@v4

.gitignore

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# --- Axiom: System Junk ---
2+
.DS_Store
3+
Thumbs.db
4+
.cache/
5+
.tmp/
6+
*.log
7+
*.swp
8+
9+
# --- Node & Dependencies ---
10+
# We use them for tools/dev, but they never touch the repo
11+
node_modules/
12+
package-lock.json
13+
npm-debug.log*
14+
15+
# --- IDEs & Environments ---
16+
.vscode/
17+
.idea/
18+
.env
19+
.env.local
20+
21+
# --- Build Output ---
22+
dist/
23+
24+
# --- Project Specific ---
25+
# If your feature tool generates temp files
26+
tools/.temp/

README.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Project Axiom
2+
3+
> **"Nullius in verba"** (Take nobody's word for it) — Royal Society Motto
4+
5+
Welcome to **Axiom**. We mistakenly decided that 500MB `node_modules` folders, 30-second builds, and debugging transpilation errors were "modern web development."
6+
7+
We were wrong.
8+
9+
Axiom is a **zero-build**, **zero-dependency**, **vanilla Web Standards** architecture. It runs directly in the browser. It respects your RAM. It respects your time.
10+
11+
---
12+
13+
## ⚡ The Architecture (TL;DR)
14+
15+
### 1. The "State" (Reactivity)
16+
**File:** `src/core/state.js`
17+
It's not a global store library. It's a `Proxy`.
18+
- **Reactive:** You touch `state.data.count`, the UI updates. Magic.
19+
- **Optimistic:** `state.mutate()` updates the UI *instantly*. If the server hiccups, it rolls back automatically. We assume success because we're optimists.
20+
- **Smart Queries:** `state.query()` handles the boring stuff (fetching, loading states, error handling, caching) so you don't have to.
21+
22+
### 2. The "Router" (Navigation)
23+
**File:** `src/core/router.js`
24+
It's roughly 200 lines of code. Popular alternatives are 30,000. existentially weigh those options.
25+
- **Parallel Loading:** It fetches your JS module AND your data simultaneously. No waterfalls here.
26+
- **Panic Mode:** If the route fails, we show a 404. If the 404 fails, we panic gracefully to avoid the White Screen of Death.
27+
- **View Transitions:** Native browser animations on navigation. Smoother than butter.
28+
29+
### 3. The "Gateway" (API)
30+
**File:** `src/core/gateway.js`
31+
A wrapper around `fetch` that actually has a brain.
32+
- **Content-Type Agnostic:** JSON? Text? Blob? It figures it out.
33+
- **Unified Headers:** Handles your auth tokens and version stamping automatically.
34+
35+
### 4. The "Components" (UI)
36+
**File:** `src/shared/base-component.js`
37+
Web Components. Native Shadow DOM.
38+
- **Surgical Updates:** We don't re-render the whole world. We find the node, we change the text. Fast.
39+
- **Theme Injection:** Adopts global styles automatically. No css-in-js libraries required.
40+
41+
---
42+
43+
## 🚀 Quick Start
44+
45+
You don't need `npm install`. You don't need `npm run build`.
46+
47+
1. **Get the code:**
48+
```bash
49+
git clone https://gitlab.com/cybercussion/axiom.git
50+
```
51+
52+
2. **Serve it:**
53+
(Browsers block ES Modules on `file://` protocol because security).
54+
(We use Vite or a SPA-aware server to ensure routing works correctly).
55+
```bash
56+
npm install
57+
npm run dev
58+
```
59+
60+
3. **Open it:**
61+
`http://localhost:3000`
62+
63+
That's it. You're developing.
64+
65+
---
66+
67+
## 🛠 Feature Generator
68+
69+
If you're lazy (and you should be), use the generator to make new distinct features.
70+
71+
```bash
72+
# Creates src/features/profile/profile.js, .css, etc.
73+
npm run feature profile
74+
```
75+
76+
## 🔍 SEO & PWA Injection
77+
78+
Don't hand-write 40 lines of `<meta>` tags like a caveman. We have a wizard for that.
79+
80+
```bash
81+
# Interactive Wizard (Title, Desc, Social Images)
82+
node tools/create-seo.js
83+
84+
# Turn it into an installable PWA (Manifest generation)
85+
node tools/create-seo.js --pwa
86+
```
87+
88+
89+
## 📦 Production Build
90+
91+
**"Wait, you said no build step?"**
92+
Correct. You don't *need* it. But if you want to crush your assets into a fine powder for production:
93+
94+
```bash
95+
# Minifies JS (Terser) & CSS (CSSO) -> /dist
96+
npm run build
97+
```
98+
99+
This is **non-destructive**. It reads your source and writes to `dist/`.
100+
101+
---
102+
103+
## 📝 Philosophy
104+
105+
**If the platform can do it, use the platform.**
106+
107+
- **Variables:** CSS Custom Properties. Not SASS Variables.
108+
- **Modules:** ES Modules (ESM). Not CommonJS require().
109+
- **State:** JS Proxy. Not a specialized reduced store library.
110+
111+
Enjoy your retrieved sanity.

docs/graphql-readme.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# GraphQL in Axiom
2+
3+
So you want to use GraphQL.
4+
5+
**STOP.** Put down `apollo-client`. Step away from `urql`.
6+
7+
You do not need a 40kb library to send a POST request string.
8+
9+
## The Axiom Way
10+
11+
GraphQL is just HTTP POST with a specific body shape. Our `gateway.js` can handle this natively with zero dependencies.
12+
13+
### 1. The Wrapper
14+
15+
You can create a specialized `graphql` helper, or extend the gateway. Here is the "vanilla" implementation:
16+
17+
```javascript
18+
// src/core/graphql.js
19+
import { gateway } from './gateway.js';
20+
21+
export const gql = (query, variables = {}) => {
22+
return gateway.request('/graphql', {
23+
method: 'POST',
24+
headers: {
25+
'Content-Type': 'application/json',
26+
},
27+
body: JSON.stringify({ query, variables })
28+
}).then(res => {
29+
if (res.errors) throw res.errors; // GraphQL-level errors
30+
return res.data;
31+
});
32+
};
33+
```
34+
35+
### 2. State Integration
36+
37+
Axiom's `state.js` doesn't care if data comes from REST or GraphQL. Use `state.query` exactly the same way.
38+
39+
```javascript
40+
// src/features/profile/profile.js
41+
import { state } from '@state';
42+
import { gql } from '@core/graphql';
43+
44+
const GET_PROFILE = `
45+
query GetProfile($id: ID!) {
46+
user(id: $id) {
47+
name
48+
avatar
49+
role
50+
}
51+
}
52+
`;
53+
54+
// In your component
55+
connectedCallback() {
56+
state.query('current-user', () => gql(GET_PROFILE, { id: '123' }));
57+
58+
this.subscribe('current-user', (user) => {
59+
this.render(user);
60+
});
61+
}
62+
```
63+
64+
### 3. Mutations (Optimistic)
65+
66+
GraphQL mutations work perfectly with `state.mutate` for optimistic UI updates.
67+
68+
```javascript
69+
const UPDATE_AVATAR = `
70+
mutation UpdateAvatar($url: String!) {
71+
updateAvatar(url: $url) {
72+
url
73+
}
74+
}
75+
`;
76+
77+
function onAvatarUpload(newUrl) {
78+
state.mutate('current-user', (current) => {
79+
// 1. Optimistic Update
80+
// Return the shape you EXPECT the server to return, or the new state
81+
return { ...current, avatar: newUrl };
82+
}, async () => {
83+
// 2. The Real Network Request
84+
return gql(UPDATE_AVATAR, { url: newUrl });
85+
});
86+
}
87+
```
88+
89+
## Summary
90+
91+
1. **Define Queries as Strings**: Template literals are fine.
92+
2. **Use `state.query`**: It handles caching, loading states, and deduplication for you.
93+
3. **Use `state.mutate`**: It handles optimistic rollbacks automatically.
94+
95+
Zero build steps. Zero extra bundles. Pure performance.

docs/realtime-readme.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Real-Time in Axiom (WebSockets)
2+
3+
Most frameworks require "Middlewares", "Thunks", or "Sagas" to handle WebSockets.
4+
Axiom requires... **Basic Javascript.**
5+
6+
Because our `state` is a Proxy, you can write to it from *anywhere*. Even a WebSocket callback.
7+
8+
## The Pattern
9+
10+
We treat the WebSocket as just another source of truth.
11+
12+
```javascript
13+
// src/core/socket.js
14+
import { state } from '@state';
15+
16+
let socket;
17+
18+
export function connect() {
19+
socket = new WebSocket('wss://api.axiom.com/v1/stream');
20+
21+
socket.onmessage = (event) => {
22+
const { type, payload } = JSON.parse(event.data);
23+
24+
// MIND BENDING PART:
25+
// We just... write to the state.
26+
// The UI updates automatically.
27+
28+
if (type === 'STOCK_UPDATE') {
29+
// If you have a list, find and update
30+
const index = state.data.stocks.findIndex(s => s.id === payload.id);
31+
if (index !== -1) {
32+
state.data.stocks[index] = payload;
33+
}
34+
}
35+
36+
if (type === 'CHAT_MESSAGE') {
37+
// Append to array
38+
state.data.messages = [...state.data.messages, payload];
39+
}
40+
};
41+
}
42+
```
43+
44+
## Usage in Components
45+
46+
Your components don't even need to know WebSockets exist. They just subscribe to the data.
47+
48+
```javascript
49+
// src/features/ticker/ticker.js
50+
import { BaseComponent } from '@shared/base-component.js';
51+
52+
class StockTicker extends BaseComponent {
53+
connectedCallback() {
54+
// This component updates whenever 'stocks' changes.
55+
// It doesn't care if it came from REST, GraphQL, or a Socket.
56+
this.subscribe('stocks', (stocks) => {
57+
this.render(stocks);
58+
});
59+
}
60+
}
61+
```
62+
63+
## Why this is "Mind Bending"
64+
65+
In Redux/Context, you'd need:
66+
1. Socket Listener
67+
2. Dispatch Action
68+
3. Reducer Case
69+
4. Selector
70+
5. Component Re-render
71+
72+
In Axiom:
73+
1. Socket Listener writes to `state.data`.
74+
2. Component updates.
75+
76+
**Nullius in verba.**

0 commit comments

Comments
 (0)