- JavaScript 69.6%
- CSS 17.8%
- HTML 12.6%
| node_modules | ||
| public | ||
| readme | ||
| uploads | ||
| .env | ||
| env.example | ||
| gitignore | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| server.js | ||
Innovative Axis
A secure, read-only Node.js markdown reader with session-based protection and Cloudflare R2 storage.
Features
- 🔒 Session-Based Security: Content only accessible through website UI
- ☁️ R2 Cloud Storage: Documents stored in Cloudflare R2
- 🎨 Professional Themes: 5 beautiful themes (Dark, Light, Ocean, Forest, Sunset)
- 📱 Responsive Layout: Resizable containers with flexible positioning
- 🔍 Smart Search & Filters: Search content and filter by tags
- 📥 Clean Downloads: Download markdown without metadata
- 🛡️ Security Hardened: Helmet, rate limiting, input sanitization
Prerequisites
- Node.js (v18 or higher)
- npm
- Cloudflare R2 account and bucket
Installation
- Clone and install dependencies:
npm install
-
Add ReadexPro font files to
public/fonts/:- ReadexPro-Light.ttf
- ReadexPro-Regular.ttf
- ReadexPro-Medium.ttf
- ReadexPro-SemiBold.ttf
-
Configure environment variables:
cp .env.example .env
- Edit
.envwith your R2 credentials:
# Server Configuration
PORT=3000
NODE_ENV=development
# Session Security (REQUIRED - CHANGE IN PRODUCTION!)
SESSION_SECRET=your-secure-random-string-here
# Cloudflare R2 Configuration
R2_ACCOUNT_ID=your-account-id
R2_ACCESS_KEY_ID=your-access-key
R2_SECRET_ACCESS_KEY=your-secret-key
R2_BUCKET_NAME=your-bucket-name
# R2 Jurisdiction (optional: default, eu, fedramp)
R2_JURISDICTION=default
R2 Bucket Structure
Your R2 bucket should be organized as follows:
your-bucket/
├── documents/
│ ├── doc1.md
│ ├── doc2.md
│ └── doc3.md
└── assets/
├── doc1/
│ ├── image1.png
│ └── image2.jpg
└── doc2/
└── diagram.svg
Markdown File Format
Each markdown file must include metadata at the top:
<!-- META
ID: unique-document-id
Tag: Category
Title: Document Title
Description: Brief description shown in feed
-->
# Your Content Here
Regular markdown content with support for:
- Images: ``
- Code blocks
- Tables
- And all standard markdown features
Metadata Fields:
ID: Unique identifier (used in URLs and asset paths)Tag: Category/tag for filteringTitle: Document title (shown in feed and downloads)Description: Brief description (shown in feed)
Running the Application
Development mode (with auto-reload):
npm run dev
Production mode:
npm start
The application will be available at http://localhost:3000
Security Features
🔐 Session-Based Protection
How it works:
- User visits homepage → Server creates session cookie
- User browses documents → All API calls require valid session
- Direct API access (bots, scrapers) → Rejected with "Please visit website" message
What's protected:
- ✅
GET /api/files- Document list - ✅
GET /api/file/:id- Document content - ✅
GET /api/download/:id- Document downloads - ✅
GET /assets/:id/:filename- Asset files
What's public:
- ✅ Homepage (creates session)
- ✅ Static files (CSS, JS, fonts)
- ✅ Health check endpoint
🛡️ Additional Security
- Helmet: Security headers (CSP, XSS protection)
- Rate Limiting: 100 requests per 15 minutes per IP
- Input Sanitization: Path traversal prevention
- HTTPS Enforcement: Automatic redirect in production
- Session Security: HTTPOnly, SameSite cookies
- Size Limits: Request body limited to 1MB
Usage
For Visitors
- Open the application in your browser
- Select a document from the feed panel
- Read content with beautiful markdown rendering
- Download documents using the "Download .md" button
- Switch themes and adjust layout as desired
Theme Switching
Click the hamburger menu (☰) and select from:
- Dark (default)
- Light
- Ocean
- Forest
- Sunset
Layout Adjustment
- Resize: Drag the space between containers
- Swap: Click the swap button (⇄) in reader header
Search & Filter
- Search: Click search icon, type to filter documents
- Filter: Click filter icon, select a tag to filter by category
API Endpoints
All endpoints require a valid session cookie (created by visiting the homepage).
GET /api/files
Returns list of all documents with metadata.
Response:
[
{
"id": "unique-doc-id",
"tag": "Tutorial",
"title": "Getting Started",
"description": "Learn the basics"
}
]
GET /api/file/:id
Returns document content without metadata.
Response:
{
"content": "# Document Content\n\nMarkdown here...",
"id": "unique-doc-id"
}
GET /api/download/:id
Downloads document as .md file (uses title from metadata for filename).
GET /assets/:id/:filename
Proxies asset files from R2 (images, PDFs, etc.).
GET /api/health
Health check endpoint (no session required).
Response:
{
"status": "healthy",
"timestamp": "2024-01-01T00:00:00.000Z",
"environment": "production"
}
Project Structure
innovative-axis/
├── public/
│ ├── fonts/ # ReadexPro font files
│ ├── css/
│ │ └── styles.css # All styling
│ ├── js/
│ │ └── app.js # Frontend JavaScript
│ └── index.html # Main HTML
├── server.js # Express server with R2 integration
├── package.json
├── .env.example # Environment variables template
├── .env # Your configuration (not in git)
├── .gitignore
└── README.md
Uploading Documents
This app is read-only. Use a separate application to upload documents to your R2 bucket.
Your upload app should:
- Validate markdown has proper metadata
- Upload to
documents/folder in R2 - Upload assets to
assets/{doc-id}/folder - Use appropriate permissions (write access to R2)
Production Deployment
Pre-deployment Checklist
- Change
SESSION_SECRETto a secure random string - Set
NODE_ENV=production - Configure R2 credentials
- Set up HTTPS/SSL certificate
- Configure reverse proxy (nginx/Cloudflare)
- Review rate limits and adjust if needed
Environment Variables
All required variables must be set:
SESSION_SECRET- CRITICAL: Must be changed from defaultR2_ACCOUNT_ID- Your Cloudflare account IDR2_ACCESS_KEY_ID- R2 API token access keyR2_SECRET_ACCESS_KEY- R2 API token secretR2_BUCKET_NAME- Your R2 bucket name
Deployment Platforms
Cloudflare Workers:
- Set environment variables in Workers dashboard
- Deploy with Wrangler CLI
Other Platforms (Heroku, Railway, DigitalOcean):
- Set environment variables in platform dashboard
- Ensure Node.js v18+ runtime
Technologies Used
- Backend: Node.js, Express
- Storage: Cloudflare R2 (S3-compatible)
- Security: Helmet, express-rate-limit, express-session
- Markdown: Marked.js
- Frontend: Vanilla JavaScript, HTML5, CSS3
- Font: ReadexPro family
Security Best Practices
- Always use HTTPS in production
- Never commit
.envfile to git - Use strong SESSION_SECRET (32+ random characters)
- Keep dependencies updated (
npm audit fix) - Monitor rate limit violations
- Use read-only R2 credentials for this app
- Regular security audits
Troubleshooting
"Missing required environment variables" error
Check that all R2 variables are set in .env file.
Session not persisting
Ensure cookies are enabled in browser. Check that SESSION_SECRET is set.
Documents not loading
- Verify R2 credentials are correct
- Check bucket name and document paths
- Ensure documents have proper metadata format
- Check R2 access permissions
Assets not displaying
Verify asset paths match folder structure in R2 and document metadata ID.
License
MIT