Build and ship a portfolio site

A clean single-page portfolio with no build step and no backend — write HTML and CSS, drop them in public/, and let the static-site setup's nginx serve them fast. Deploy, style, and give it a real domain.

A portfolio is the perfect first thing to ship: it's just HTML and CSS, there's no backend to break, and at the end you have a real link to put on your résumé or in your Discord bio. This build uses the static-site setup — a real nginx web server that serves your files fast — so there's nothing to run and nothing to keep online but the server itself.

At a glance
You're building A one-page portfolio: about, projects, contact links
You need A server running the PHP Web Server application (we use only its nginx part — no PHP)
Plan Any plan
Time About twenty minutes

This guide builds on Host a static website, which sets up the nginx serving. Deploy that first, then bring your portfolio files here.

What you're building

Piece File
The page public/index.html — one page, a few sections
The look public/style.css — colors, spacing, layout
Served by nginx from the static-site setup, on your SERVER_PORT

No package.json, no index.js, no database. A static site is files on disk and a web server handing them out — that's the whole model, and it's why it's fast and cheap to run.

The files

Everything lives in the public/ folder (the static-site setup's web root).

public/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Alex Rivera — Developer</title>
  <link rel="stylesheet" href="/style.css">
</head>
<body>
  <header>
    <h1>Alex Rivera</h1>
    <p class="tagline">Backend developer &amp; server tinkerer</p>
  </header>

  <main>
    <section>
      <h2>About</h2>
      <p>I build small, reliable services and host them myself. I like databases,
         clean APIs, and things that stay up.</p>
    </section>

    <section>
      <h2>Projects</h2>
      <ul class="projects">
        <li><strong>URL Shortener</strong> — a tiny link service in Node and SQLite.</li>
        <li><strong>Status Page</strong> — watches my other servers and shows if they're up.</li>
        <li><strong>Chat Room</strong> — a real-time chat with Socket.io.</li>
      </ul>
    </section>

    <section>
      <h2>Contact</h2>
      <ul class="links">
        <li><a href="mailto:[email protected]">Email</a></li>
        <li><a href="https://github.com/yourname">GitHub</a></li>
        <li><a href="https://discord.gg/yourinvite">Discord</a></li>
      </ul>
    </section>
  </main>

  <footer><p>Hosted on Falix.</p></footer>
</body>
</html>

public/style.css:

:root { --accent: #4f46e5; --ink: #1f2937; --muted: #6b7280; }
* { box-sizing: border-box; }

body {
  font-family: system-ui, -apple-system, sans-serif;
  color: var(--ink);
  max-width: 44rem;
  margin: 0 auto;
  padding: 3rem 1.25rem;
  line-height: 1.6;
}

header { border-bottom: 2px solid var(--accent); padding-bottom: 1rem; margin-bottom: 2rem; }
h1 { margin: 0; font-size: 2.2rem; }
.tagline { color: var(--muted); margin: 0.3rem 0 0; }

section { margin-bottom: 2rem; }
h2 { font-size: 1.2rem; }

.projects, .links { list-style: none; padding: 0; }
.projects li { padding: 0.5rem 0; border-bottom: 1px solid #eee; }
.links { display: flex; gap: 1rem; }
.links a { color: var(--accent); text-decoration: none; font-weight: 600; }
.links a:hover { text-decoration: underline; }

footer { color: var(--muted); font-size: 0.85rem; border-top: 1px solid #eee; padding-top: 1rem; }

How it works

  • The file layout is the URL layout. public/index.html is your home page at /. Add public/projects/index.html and it's at /projects/. nginx serves whatever matches the path.
  • <link rel="stylesheet" href="/style.css"> loads the CSS. nginx sends it with the correct text/css content type automatically — you never configure MIME types.
  • CSS variables keep it tidy. The :root { --accent: … } block sets your theme in one place; change --accent and every link and border follows.
  • Nothing runs. There's no process of yours to crash. nginx reads the files off disk and returns them — which is why static sites are the cheapest, most reliable thing you can host.

💡 Tip: Edits to files in public/ are served live — save the file, then hard-refresh the browser (Ctrl/Cmd+Shift+R) to bypass the cache. You do not restart the server for content changes; that's only for the nginx config itself.

Ship it on Falix

  1. Deploy the Static Website setup from Host a static website — it wires your SERVER_PORT into nginx for you.
  2. Open the File Manager, go into public/, and replace the sample index.html (and add style.css) with the files above. Or drag your whole folder across over SFTP.
  3. Open your server's address from the Network page. Your portfolio loads.

That's it — a static site needs no SERVER_PORT code from you, because nginx (set up by the static template) already binds it.

🎯 Good to know: Your files survive restarts. A reinstall or switching the application wipes them like any server files, so keep the source in a Git repo — then a redeploy puts it right back, and you get version history for free. See Deploy your code with Git.

Make it yours

  • A custom 404. Add public/404.html and one line to the nginx config — the static site guide shows exactly where.
  • More pages. public/blog/index.html, public/projects/index.html — folders become clean URLs.
  • A photo or favicon. Drop images in public/ and reference them; nginx serves them with the right type.
  • Outgrow hand-written HTML? A static-site generator turns Markdown into pages — see Build a blog with Eleventy.

HTML and CSS themselves are vast; MDN Web Docs is the reference the whole web uses.

Give it a real address

address:port is fine for testing but not for sharing. The Network page's Reverse Proxy puts a real domain in front with automatic HTTPS on any plan — follow Domains and HTTPS. A free yourname.falix.org works, or bring your own domain.

Troubleshooting

  • 404 on the home page — it must be named exactly public/index.html, lowercase. Check spelling and that it's inside public/.
  • CSS doesn't apply — the href path is wrong. With the file at public/style.css, the link is /style.css (leading slash). Hard-refresh to clear the cache.
  • Changed a file but see the old version — browser cache, not the server. Static files are served live; hard-refresh (Ctrl/Cmd+Shift+R).
  • Whole site won't load — a reachability problem, not a file one: I can't reach my app.

Next steps

Was this guide helpful?