Project Plug

Docs

How Project Plug works

Create your list

Sign up, claim a handle, and add your projects in the dashboard. Each project has a name, a description, and a link. The handle becomes your public address at /u/your-handle.

Drop one line on any site

Paste this anywhere on a page. Replace your-username with your handle.

<div data-project-plug="your-username" data-limit="5"></div>
<script src="https://project-plug.vercel.app/project-plug.js" defer></script>

That is the whole snippet. The script renders a plain unordered list inside the div AND auto-loads your saved stylesheet so your designed look applies automatically. It also auto-hides the project that lives on the current site, so an embed on aurora.com won't link back to itself.

Multiple looks per user. Save as many named styles as you want in Customize the look (e.g. warm-bento, monochrome). Pick one per embed:

<div
  data-project-plug="your-username"
  data-project-plug-style="warm-bento"
></div>
<script src="https://project-plug.vercel.app/project-plug.js" defer></script>

If you want full control of the styling on the host site, add data-project-plug-style="off" to the div. The list still renders, but nothing is injected into <head> — your own CSS wins.

Style it (three ways, pick one)

Easiest. Open Customize the look in the dashboard. Pick a preset, tweak it, save. Your public profile updates and a hosted stylesheet is served at /u/your-handle/styles.css. Link to it from any site:

<link rel="stylesheet" href="https://project-plug.vercel.app/u/your-handle/styles.css">

Manual copy. The customizer also exposes the generated CSS so you can paste it directly into your own stylesheet and edit it further.

From scratch. If you prefer, ignore the customizer entirely and target the class names yourself.

.project-plug-list { list-style: none; padding: 0; margin: 0; }
.project-plug-item { margin: 0 0 0.75rem; }
.project-plug-link { display: block; padding: 1rem; border: 1px solid #e5e5e5; border-radius: 8px; text-decoration: none; color: inherit; }
.project-plug-title { display: block; font-weight: 600; }
.project-plug-description { display: block; color: #666; font-size: 0.875rem; margin-top: 0.25rem; }
.project-plug-view-all { display: inline-block; margin-top: 0.75rem; }

Attributes you can set on the div

data-project-plugrequired. Your username.
data-project-plug-stylePick which saved style to load. '<slug>' loads /u/<your-handle>/styles/<slug>.css. Absent → the user's default style (/u/<your-handle>/styles.css). 'off' → no stylesheet injected; style the list yourself.
data-project-plug-stylesLegacy alias. 'off' (or 'false', 'none', 'manual') opts out of stylesheet injection. Use data-project-plug-style instead for new embeds.
data-project-plug-skip-selftrue (default) — hide any project whose URL is on the current host page (same hostname and matching path prefix). Set to false to always include every project, even the one the embed is sitting on.
data-limit1 to 100. Default 5.
data-view-alltrue (default) or false. Append a 'View all' link when total exceeds the limit.
data-view-all-textDefault 'View all {count}'. The literal {count} is replaced.
data-fieldsComma list of fields to render. Default 'title,description'. Use 'title' for a names-only list.
data-target_blank (default) or _self for the project links.
data-class-prefixDefault 'project-plug'. Change to 'myproj' to get .myproj-list, .myproj-item, etc. Note: auto-load of the saved stylesheet is skipped when a custom prefix is used (your CSS targets different class names).
data-loading-textLoading state. Default 'Loading projects...'.
data-empty-textEmpty state. Default 'No projects yet.'.

Class names emitted (with default prefix)

.project-plug-listOuter <ul>
.project-plug-itemEach <li>
.project-plug-linkThe <a> wrapping each item
.project-plug-titleProject name <span>
.project-plug-descriptionProject description <span>
.project-plug-view-allThe View all <a>
.project-plug-loadingShown while fetching
.project-plug-emptyShown when there are zero projects
.project-plug-errorShown if the fetch fails

JSON API (if you do not want the loader)

For static site generators, server-rendered apps, or anything where you want the data directly. CORS is open and the response is cached for one minute.

GET https://project-plug.vercel.app/api/u/your-username/products?limit=5
{
  "user": { "username": "your-username", "display_name": null },
  "total": 12,
  "limit": 5,
  "products": [
    { "id": "...", "slug": "my-app", "title": "My App", "description": "...", "url": "https://...", "position": 0 }
  ],
  "profile_url": "https://project-plug.vercel.app/u/your-username"
}

Public profile

Every user gets a public profile at /u/your-handle. This is where the View all link points by default. The profile uses your saved style automatically.

Ready to try it? Create your list.

Docs — Project Plug