Artistier Docs

Setup guide for the self-hosted artist platform

1. Requirements

Optional for NFT storefront:

2. Installation

Clone the repo

git clone https://github.com/AleBlom/artistier.git
cd artistier

Directory structure

artistier/
├── config/          ← configuration
├── contract/        ← Sui Move smart contract
├── cron/            ← email drip cron script
├── logs/            ← log files (auto-created)
└── public/          ← web root
    ├── api/         ← JSON API endpoints
    ├── css/         ← stylesheets
    ├── db/          ← SQLite database + init script
    ├── js/          ← frontend scripts
    └── img/         ← favicon + uploads

Option A: VPS / Dedicated Server

Point your Apache DocumentRoot to the public/ directory:

<VirtualHost *:80>
    ServerName yourdomain.com
    DocumentRoot /var/www/artistier/public
    <Directory /var/www/artistier/public>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

With this setup, config/, cron/, and logs/ are outside the web root entirely — no web access possible.

Option B: Shared Hosting

On shared hosting you typically can't change the document root. Copy everything into your web root:

public_html/          ← your web root
├── config/           ← protected by .htaccess
├── cron/             ← protected by .htaccess
├── logs/             ← protected by .htaccess
├── .htaccess
├── bootstrap.php
├── index.php
├── api/
├── css/
├── db/
├── js/
└── img/
A bootstrap.php auto-detects which layout you're using — no path editing needed. Sensitive directories are protected by both their own .htaccess deny rules and rewrite rules in the main .htaccess, so your API keys and config files are never web-accessible even though they're inside the web root.

Copy config files

cp config/site.example.php config/site.php
cp config/email.example.php config/email.php
cp config/nft.example.php config/nft.php
cp config/homepage.example.php config/homepage.php

Add your profile picture

Place a square image at public/img/pfp.jpg (or public_html/img/pfp.jpg on shared hosting).

Add favicon files

Replace the files in public/img/:

3. Configuration

All configuration lives in four PHP files using define() constants.

config/site.php

Core site identity and social links.

ConstantDescription
SITE_NAMEYour display name
SITE_TAGLINEShort intro shown on homepage
SITE_DOMAINYour domain (shown in footer)
SITE_LEGAL_ENTITYCompany name for privacy policy
SITE_LEGAL_ADDRESSAddress for privacy policy
SITE_CONTACT_EMAILContact email for privacy policy
TEST_EMAILEmail address for admin preview sends
SOCIAL_*Social links (Instagram, TikTok, X, LinkedIn, YouTube). Leave empty to hide.

config/email.php

ElasticEmail API credentials for the newsletter.

ConstantDescription
EMAIL_API_KEYYour ElasticEmail API key
EMAIL_FROMSender email address
EMAIL_FROM_NAMESender display name
SITE_URLFull URL with https (for unsubscribe links)

config/nft.php

Sui blockchain and Walrus storage settings. Leave defaults until you deploy the contract.

ConstantDescription
SUI_NETWORKtestnet or mainnet
SUI_RPC_URLSui fullnode RPC endpoint
SUI_PACKAGE_IDDeployed contract package ID
SUI_MARKETPLACE_IDShared Marketplace object ID
SUI_ADMIN_ADDRESSAdmin wallet address
SUI_ADMIN_CAP_IDAdminCap object ID
WALRUS_PUBLISHER_URLWalrus publisher for uploads
WALRUS_AGGREGATOR_URLWalrus aggregator for serving images
WALRUS_EPOCHSStorage duration in epochs
STOREFRONT_*Name, description, and artist for the storefront

config/homepage.php

Optional HTML sections appended to the homepage between the Art section and the Blog. Use this for commissions, exhibitions, project links, or anything else. See the example file for the card format.

4. Database

The database is a single SQLite file at db/blog.db. Initialize it by running:

php public/db/init.php        # Option A (VPS)
php db/init.php               # Option B (shared hosting)

This creates the tables:

TablePurpose
postsBlog posts (slug, title, content, timestamps)
settingsKey-value store (admin password hash)
subscribersNewsletter subscribers with status and drip position
email_sequenceDrip email content (subject, HTML body, text body)
collectionsNFT collections with cover images and metadata
nftsIndividual NFTs with pricing, status, and Sui object IDs
nft_configRuntime NFT configuration
The default admin password is changeme. Log in and change it immediately.

The .htaccess blocks direct access to .db files, but placing the database outside the web root is even safer if your hosting allows it.

5. NFT Storefront Setup

The NFT storefront is optional. Skip this section if you only need blog + newsletter.

Deploy the smart contract

Install the Sui CLI, then:

cd contract
sui client publish --gas-budget 100000000

The output contains the IDs you need. Look for:

Copy these into config/nft.php.

Walrus image storage

NFT images are uploaded to Walrus decentralized storage from the admin dashboard. The default config points to testnet. For mainnet:

define('WALRUS_PUBLISHER_URL', 'https://publisher.walrus.space');
define('WALRUS_AGGREGATOR_URL', 'https://aggregator.walrus.space');

Wallet connection

Buyers connect their Sui wallet (browser extension) to purchase NFTs with USDC. The storefront handles wallet detection, transaction building, and purchase confirmation automatically.

Going to mainnet

  1. Redeploy the contract on mainnet: sui client switch --env mainnet
  2. Update SUI_NETWORK to mainnet in config/nft.php
  3. Update SUI_RPC_URL to the mainnet endpoint
  4. Update Walrus URLs to mainnet endpoints
  5. Update the contract IDs with the new mainnet values

6. Newsletter & Cron

ElasticEmail setup

  1. Sign up at elasticemail.com
  2. Get your API key from Settings → API
  3. Verify your sender domain
  4. Add your API key and sender info to config/email.php

Cron job

The drip sequence sends one email per subscriber per day. Set up a daily cron:

# Run at 9 AM daily
0 9 * * * php /path/to/cron/email-sequence.php

On shared hosting, use your host's cron job manager (cPanel → Cron Jobs).

How the drip works

  1. New subscriber signs up → status pending, sequence position 0
  2. Subscriber confirms via email link → status active
  3. Cron runs daily → sends the email at the subscriber's current position
  4. After sending, position advances by 1
  5. When position exceeds the last email, nothing more is sent

Email template

The email wrapper template is at cron/email-template.php. Edit it to match your branding.

7. Admin Dashboard

Access the admin at /admin after logging in on the homepage.

The admin has four tabs:

8. Customization

Homepage sections

Edit config/homepage.php to add custom sections between the Art grid and the Blog. Use the card format from the example file:

<section class="section">
    <h2 class="section-title">Commissions</h2>
    <div class="projects-grid">
        <a href="/art" class="project-card">
            <div class="project-logo" style="...">...</div>
            <div>
                <h3>Custom Portraits</h3>
                <p>Starting at $200.</p>
            </div>
        </a>
    </div>
</section>

CSS

All styles are in css/style.css (public site) and css/admin.css (admin dashboard). The design uses CSS custom properties where applicable.

Favicon

Replace the files in img/. The HTML references favicon.ico, favicon-32x32.png, apple-touch-icon.png, and android-chrome-192x192.png.

Blog post images

Posts support image uploads via the post editor. Images are stored in img/uploads/.

9. Security

Artistier uses layered protection for sensitive files, especially important on shared hosting where config/ (containing API keys) is inside the web root.

Directory protection

DirectoryContainsProtection
config/API keys, secrets, site settings.htaccess deny + rewrite rule
cron/Email sending scripts.htaccess deny + rewrite rule
logs/Log files.htaccess deny + rewrite rule
db/SQLite database.htaccess deny + <Files> rule

Each sensitive directory has its own .htaccess with Require all denied. The main .htaccess also has rewrite rules blocking /config/, /cron/, and /logs/ as a second layer.

On VPS setups (Option A), config/, cron/, and logs/ are outside the web root entirely, so they're never web-accessible regardless of .htaccess rules.

Admin authentication

Passwords are hashed with PHP's password_hash() (bcrypt). Sessions are server-side. The default password is changeme — change it immediately after first login.

Recommendations

10. FAQ

Do I need the NFT storefront?

No. The blog and newsletter work independently. Leave config/nft.php with empty IDs and the art sections won't appear.

Can I use a different email provider?

The cron script sends via a simple HTTP POST to ElasticEmail's API. You could swap it for any transactional email API (SendGrid, Mailgun, etc.) by editing cron/email-sequence.php and the subscribe/confirm endpoints in api/.

Is the admin password secure?

Passwords are hashed with PHP's password_hash() (bcrypt). The default is changeme — change it after first login. Sessions are server-side.

Can I run this on Nginx?

Yes, but you'll need to convert the .htaccess rewrite rules to Nginx config. The key rules route /post/slug, /art/collection/piece, /admin, and a few other clean URLs to their PHP files.

How do I back up?

Copy db/blog.db and img/uploads/. That's everything. Config files don't change at runtime.

Where are the logs?

Email sequence logs go to logs/email-sequence.log and logs/email-sequence-error.log. The logs/ directory is created automatically.