feat(T01): bootstrap IHP v1.5 project scaffold

Merged ihp-new generated scaffold into repo. Sets appName to inter-hub,
adds Nix flake with IHP inputs, devenv config, and standard IHP project
structure. Nix + ihp-new + direnv installed system-wide.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-27 01:36:18 +00:00
parent 8b6ce5bbc8
commit ff11913d5c
32 changed files with 3247 additions and 173 deletions

34
.envrc Normal file
View File

@@ -0,0 +1,34 @@
#!/usr/bin/env bash
# See https://github.com/cachix/devenv/blob/main/templates/flake-parts/.envrc
if ! has nix_direnv_version || ! nix_direnv_version 3.1.0; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.1.0/direnvrc" "sha256-yMJ2OVMzrFaDPn7q8nCBZFRYpL/f0RcHzhmw/i6btJM="
fi
export DEVENV_IN_DIRENV_SHELL=true
watch_file flake.nix
watch_file flake.lock
mkdir -p "$PWD/.devenv"
DEVENV_ROOT_FILE="$PWD/.devenv/root"
printf %s "$PWD" >"$DEVENV_ROOT_FILE"
if ! use flake . --override-input devenv-root "file+file://$DEVENV_ROOT_FILE" --accept-flake-config; then
echo "devenv could not be built. The devenv environment was not loaded. Make the necessary changes to devenv.nix and hit enter to try again." >&2
fi
# Include .env file if it exists locally. Use the .env file to load env vars that you don't want to commit to git
if [ -f .env ]
then
set -o allexport
source .env
set +o allexport
fi
# Add your env vars here
#
# E.g. export AWS_ACCESS_KEY_ID="XXXXX"
# SMTP config for local development.
export SMTP_HOST="127.0.0.1" # On some computers may need `127.0.1.1` instead.
export SMTP_PORT="1025"
export SMTP_ENCRYPTION="Unencrypted"

4
.ghci Normal file
View File

@@ -0,0 +1,4 @@
:set -XNoImplicitPrelude
:def loadFromIHP \file -> (System.Environment.getEnv "IHP_LIB") >>= (\ihpLib -> readFile (ihpLib <> "/" <> file))
:loadFromIHP applicationGhciConfig
import IHP.Prelude

3
.gitattributes vendored Normal file
View File

@@ -0,0 +1,3 @@
* text=auto eol=lf
*.sql text
*.hs text

24
.github/workflows/nix-flake-check.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: Test
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: wimpysworld/nothing-but-nix@main
with:
hatchet-protocol: 'rampage'
- uses: DeterminateSystems/nix-installer-action@main
with:
determinate: true
extra-conf: "lazy-trees = true"
- uses: cachix/cachix-action@v16
with:
name: digitallyinduced
skipPush: true
- uses: DeterminateSystems/magic-nix-cache-action@main
- run: nix flake check --impure -L

198
.gitignore vendored
View File

@@ -1,176 +1,28 @@
# ---> Python .DS_Store
# Byte-compiled / optimized / DLL files .idea
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env .env
.venv tmp
env/ result
venv/ node_modules
ENV/ bin
env.bak/ *.iml
venv.bak/ Generated
dist
dist-newstyle
*.dyn_hi
*.dyn_o
*.hi
*.o
build
gen
del
static/prod.*
Config/client_session_key.aes
# Spyder project settings # Ignore locally checked out IHP version
.spyderproject IHP
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Ruff stuff:
.ruff_cache/
# PyPI configuration file
.pypirc
# devenv.sh
.devenv*
devenv.local.nix
.direnv

415
.stylish-haskell.yaml Normal file
View File

@@ -0,0 +1,415 @@
# stylish-haskell configuration file
# ==================================
# The stylish-haskell tool is mainly configured by specifying steps. These steps
# are a list, so they have an order, and one specific step may appear more than
# once (if needed). Each file is processed by these steps in the given order.
steps:
# Convert some ASCII sequences to their Unicode equivalents. This is disabled
# by default.
# - unicode_syntax:
# # In order to make this work, we also need to insert the UnicodeSyntax
# # language pragma. If this flag is set to true, we insert it when it's
# # not already present. You may want to disable it if you configure
# # language extensions using some other method than pragmas. Default:
# # true.
# add_language_pragma: true
# Format module header
#
# Currently, this option is not configurable and will format all exports and
# module declarations to minimize diffs
#
# - module_header:
# # How many spaces use for indentation in the module header.
# indent: 4
#
# # Should export lists be sorted? Sorting is only performed within the
# # export section, as delineated by Haddock comments.
# sort: true
#
# # See `separate_lists` for the `imports` step.
# separate_lists: true
#
# # When to break the "where".
# # Possible values:
# # - exports: only break when there is an explicit export list.
# # - single: only break when the export list counts more than one export.
# # - inline: only break when the export list is too long. This is
# # determined by the `columns` setting. Not applicable when the export
# # list contains comments as newlines will be required.
# # - always: always break before the "where".
# break_where: exports
#
# # Where to put open bracket
# # Possible values:
# # - same_line: put open bracket on the same line as the module name, before the
# # comment of the module
# # - next_line: put open bracket on the next line, after module comment
# open_bracket: next_line
# Format record definitions. This is disabled by default.
#
# You can control the layout of record fields. The only rules that can't be configured
# are these:
#
# - "|" is always aligned with "="
# - "," in fields is always aligned with "{"
# - "}" is likewise always aligned with "{"
#
# - records:
# # How to format equals sign between type constructor and data constructor.
# # Possible values:
# # - "same_line" -- leave "=" AND data constructor on the same line as the type constructor.
# # - "indent N" -- insert a new line and N spaces from the beginning of the next line.
# equals: "indent 2"
#
# # How to format first field of each record constructor.
# # Possible values:
# # - "same_line" -- "{" and first field goes on the same line as the data constructor.
# # - "indent N" -- insert a new line and N spaces from the beginning of the data constructor
# first_field: "indent 2"
#
# # How many spaces to insert between the column with "," and the beginning of the comment in the next line.
# field_comment: 2
#
# # How many spaces to insert before "deriving" clause. Deriving clauses are always on separate lines.
# deriving: 2
#
# # How many spaces to insert before "via" clause counted from indentation of deriving clause
# # Possible values:
# # - "same_line" -- "via" part goes on the same line as "deriving" keyword.
# # - "indent N" -- insert a new line and N spaces from the beginning of "deriving" keyword.
# via: "indent 2"
#
# # Sort typeclass names in the "deriving" list alphabetically.
# sort_deriving: true
#
# # Whether or not to break enums onto several lines
# #
# # Default: false
# break_enums: false
#
# # Whether or not to break single constructor data types before `=` sign
# #
# # Default: true
# break_single_constructors: true
#
# # Whether or not to curry constraints on function.
# #
# # E.g: @allValues :: Enum a => Bounded a => Proxy a -> [a]@
# #
# # Instead of @allValues :: (Enum a, Bounded a) => Proxy a -> [a]@
# #
# # Default: false
# curried_context: false
# Align the right hand side of some elements. This is quite conservative
# and only applies to statements where each element occupies a single
# line.
# Possible values:
# - always - Always align statements.
# - adjacent - Align statements that are on adjacent lines in groups.
# - never - Never align statements.
# All default to always.
- simple_align:
cases: always
top_level_patterns: always
records: always
multi_way_if: always
# Import cleanup
- imports:
# There are different ways we can align names and lists.
#
# - global: Align the import names and import list throughout the entire
# file.
#
# - file: Like global, but don't add padding when there are no qualified
# imports in the file.
#
# - group: Only align the imports per group (a group is formed by adjacent
# import lines).
#
# - none: Do not perform any alignment.
#
# Default: global.
align: none
# The following options affect only import list alignment.
#
# List align has following options:
#
# - after_alias: Import list is aligned with end of import including
# 'as' and 'hiding' keywords.
#
# > import qualified Data.List as List (concat, foldl, foldr, head,
# > init, last, length)
#
# - with_alias: Import list is aligned with start of alias or hiding.
#
# > import qualified Data.List as List (concat, foldl, foldr, head,
# > init, last, length)
#
# - with_module_name: Import list is aligned `list_padding` spaces after
# the module name.
#
# > import qualified Data.List as List (concat, foldl, foldr, head,
# init, last, length)
#
# This is mainly intended for use with `pad_module_names: false`.
#
# > import qualified Data.List as List (concat, foldl, foldr, head,
# init, last, length, scanl, scanr, take, drop,
# sort, nub)
#
# - new_line: Import list starts always on new line.
#
# > import qualified Data.List as List
# > (concat, foldl, foldr, head, init, last, length)
#
# - repeat: Repeat the module name to align the import list.
#
# > import qualified Data.List as List (concat, foldl, foldr, head)
# > import qualified Data.List as List (init, last, length)
#
# Default: after_alias
list_align: after_alias
# Right-pad the module names to align imports in a group:
#
# - true: a little more readable
#
# > import qualified Data.List as List (concat, foldl, foldr,
# > init, last, length)
# > import qualified Data.List.Extra as List (concat, foldl, foldr,
# > init, last, length)
#
# - false: diff-safe
#
# > import qualified Data.List as List (concat, foldl, foldr, init,
# > last, length)
# > import qualified Data.List.Extra as List (concat, foldl, foldr,
# > init, last, length)
#
# Default: true
pad_module_names: true
# Long list align style takes effect when import is too long. This is
# determined by 'columns' setting.
#
# - inline: This option will put as much specs on same line as possible.
#
# - new_line: Import list will start on new line.
#
# - new_line_multiline: Import list will start on new line when it's
# short enough to fit to single line. Otherwise it'll be multiline.
#
# - multiline: One line per import list entry.
# Type with constructor list acts like single import.
#
# > import qualified Data.Map as M
# > ( empty
# > , singleton
# > , ...
# > , delete
# > )
#
# Default: inline
long_list_align: inline
# Align empty list (importing instances)
#
# Empty list align has following options
#
# - inherit: inherit list_align setting
#
# - right_after: () is right after the module name:
#
# > import Vector.Instances ()
#
# Default: inherit
empty_list_align: inherit
# List padding determines indentation of import list on lines after import.
# This option affects 'long_list_align'.
#
# - <integer>: constant value
#
# - module_name: align under start of module name.
# Useful for 'file' and 'group' align settings.
#
# Default: 4
list_padding: 4
# Separate lists option affects formatting of import list for type
# or class. The only difference is single space between type and list
# of constructors, selectors and class functions.
#
# - true: There is single space between Foldable type and list of it's
# functions.
#
# > import Data.Foldable (Foldable (fold, foldl, foldMap))
#
# - false: There is no space between Foldable type and list of it's
# functions.
#
# > import Data.Foldable (Foldable(fold, foldl, foldMap))
#
# Default: true
separate_lists: true
# Space surround option affects formatting of import lists on a single
# line. The only difference is single space after the initial
# parenthesis and a single space before the terminal parenthesis.
#
# - true: There is single space associated with the enclosing
# parenthesis.
#
# > import Data.Foo ( foo )
#
# - false: There is no space associated with the enclosing parenthesis
#
# > import Data.Foo (foo)
#
# Default: false
space_surround: false
# Post qualify option moves any qualifies found in import declarations
# to the end of the declaration. This also adjust padding for any
# unqualified import declarations.
#
# - true: Qualified as <module name> is moved to the end of the
# declaration.
#
# > import Data.Bar
# > import Data.Foo qualified as F
#
# - false: Qualified remains in the default location and unqualified
# imports are padded to align with qualified imports.
#
# > import Data.Bar
# > import qualified Data.Foo as F
#
# Default: false
post_qualify: false
# Language pragmas
- language_pragmas:
# We can generate different styles of language pragma lists.
#
# - vertical: Vertical-spaced language pragmas, one per line.
#
# - compact: A more compact style.
#
# - compact_line: Similar to compact, but wrap each line with
# `{-# LANGUAGE #-}'.
#
# - vertical_compact: Similar to vertical, but use only one language pragma.
#
# Default: vertical.
style: vertical
# Align affects alignment of closing pragma brackets.
#
# - true: Brackets are aligned in same column.
#
# - false: Brackets are not aligned together. There is only one space
# between actual import and closing bracket.
#
# Default: true
align: true
# stylish-haskell can detect redundancy of some language pragmas. If this
# is set to true, it will remove those redundant pragmas. Default: true.
remove_redundant: true
# Language prefix to be used for pragma declaration, this allows you to
# use other options non case-sensitive like "language" or "Language".
# If a non correct String is provided, it will default to: LANGUAGE.
language_prefix: LANGUAGE
# Replace tabs by spaces. This is disabled by default.
# - tabs:
# # Number of spaces to use for each tab. Default: 8, as specified by the
# # Haskell report.
# spaces: 8
# Remove trailing whitespace
- trailing_whitespace: {}
# Squash multiple spaces between the left and right hand sides of some
# elements into single spaces. Basically, this undoes the effect of
# simple_align but is a bit less conservative.
# - squash: {}
# A common setting is the number of columns (parts of) code will be wrapped
# to. Different steps take this into account.
#
# Set this to null to disable all line wrapping.
#
# Default: 80.
columns: 80
# By default, line endings are converted according to the OS. You can override
# preferred format here.
#
# - native: Native newline format. CRLF on Windows, LF on other OSes.
#
# - lf: Convert to LF ("\n").
#
# - crlf: Convert to CRLF ("\r\n").
#
# Default: native.
newline: native
# Sometimes, language extensions are specified in a cabal file or from the
# command line instead of using language pragmas in the file. stylish-haskell
# needs to be aware of these, so it can parse the file correctly.
#
# No language extensions are enabled by default.
language_extensions:
- BangPatterns
- BlockArguments
- BlockArguments
- DataKinds
- DefaultSignatures
- DeriveDataTypeable
- DeriveGeneric
- DerivingVia
- DisambiguateRecordFields
- DuplicateRecordFields
- EmptyDataDeriving
- FlexibleContexts
- FlexibleInstances
- FunctionalDependencies
- ImplicitParams
- InstanceSigs
- LambdaCase
- MultiParamTypeClasses
- MultiWayIf
- MultiWayIf
- NamedFieldPuns
- NoImplicitPrelude
- OverloadedLabels
- OverloadedStrings
- PackageImports
- PartialTypeSignatures
- PartialTypeSignatures
- QuasiQuotes
- Rank2Types
- RecordWildCards
- ScopedTypeVariables
- StandaloneDeriving
- TemplateHaskell
- TypeApplications
- TypeFamilies
- TypeOperators
- TypeSynonymInstances
- UndecidableInstances
# Attempt to find the cabal file in ancestors of the current directory, and
# parse options (currently only language extensions) from that.
#
# Default: true
cabal: true

73
App.cabal Normal file
View File

@@ -0,0 +1,73 @@
-- This file is only a stub file, please see default.nix for adding dependencies.
--
-- Learn more about dependency management in IHP: https://ihp.digitallyinduced.com/Guide/package-management.html
--
-- If you're looking at this file because you're trying to integrate a HLS or other tooling with your IHP project, check out the documentation on Editors and Tooling: https://ihp.digitallyinduced.com/Guide/editors.html
--
-- This cabal file is inside your project as some haskell tools only work when there's a cabal file. It's not actually used for anything besides providing support for haskell tools.
--
name: App
version: 0.1.0.0
-- synopsis:
-- description:
license: AllRightsReserved
license-file: LICENSE
author: Developers
maintainer: developers@example.com
-- copyright:
-- category:
build-type: Simple
cabal-version: >=1.10
executable App
main-is: Main.hs
-- other-modules:
-- other-extensions:
build-depends:
ihp,
base,
wai,
text,
hspec,
ihp-hspec
hs-source-dirs: .
default-language: Haskell2010
extensions:
OverloadedStrings
, NoImplicitPrelude
, ImplicitParams
, Rank2Types
, DisambiguateRecordFields
, NamedFieldPuns
, DuplicateRecordFields
, OverloadedLabels
, FlexibleContexts
, TypeSynonymInstances
, FlexibleInstances
, QuasiQuotes
, TypeFamilies
, PackageImports
, ScopedTypeVariables
, RecordWildCards
, TypeApplications
, DataKinds
, InstanceSigs
, DeriveGeneric
, MultiParamTypeClasses
, TypeOperators
, DeriveDataTypeable
, MultiWayIf
, UndecidableInstances
, BlockArguments
, PartialTypeSignatures
, LambdaCase
, DefaultSignatures
, EmptyDataDeriving
, BangPatterns
, BlockArguments
, MultiWayIf
, FunctionalDependencies
, PartialTypeSignatures
, StandaloneDeriving
, DerivingVia

0
Application/Fixtures.sql Normal file
View File

View File

@@ -0,0 +1,5 @@
module Application.Helper.Controller where
import IHP.ControllerPrelude
-- Here you can add functions which are available in all your controllers

View File

@@ -0,0 +1,5 @@
module Application.Helper.View where
import IHP.ViewPrelude
-- Here you can add functions which are available in all your views

1
Application/Schema.sql Normal file
View File

@@ -0,0 +1 @@
-- Your database schema. Use the Schema Designer at http://localhost:8001/ to add some tables.

View File

@@ -0,0 +1,12 @@
module Application.Script.Prelude
( module IHP.ControllerPrelude
, module Generated.Types
, module IHP.Prelude
, module IHP.ScriptSupport
)
where
import IHP.Prelude
import IHP.ControllerPrelude
import Generated.Types
import IHP.ScriptSupport

11
Config/Config.hs Normal file
View File

@@ -0,0 +1,11 @@
module Config where
import IHP.Prelude
import IHP.Environment
import IHP.FrameworkConfig
config :: ConfigBuilder
config = do
-- See https://ihp.digitallyinduced.com/Guide/config.html
-- for what you can do here
pure ()

View File

View File

@@ -0,0 +1,92 @@
{ ihp, lib, pkgs, ... }: {
imports = [
./hardware-configuration.nix
# This sets several default options. It's designed for simple, small apps where the database and app server
# are on the same host.
#
# See https://github.com/digitallyinduced/ihp/blob/master/NixSupport/nixosModules/appWithPostgres.nix for details
#
# For more complex production deployments, consider ihp.nixosModules.app (https://github.com/digitallyinduced/ihp/blob/master/NixSupport/nixosModules/app.nix)
ihp.nixosModules.appWithPostgres
];
networking.firewall = {
enable = true;
allowedTCPPorts = [ 22 80 443 ];
};
# Enable the Let's encrypt certificate
security.acme.defaults.email = "CHANGE-ME@example.com";
# Accept the terms of service of the Let's encrypt provider.
security.acme.acceptTerms = true;
services.nginx = {
virtualHosts."CHANGE-ME.com" = {
# Uncomment to have http auth with username `foo` and password `bar`.
# basicAuth = { foo = "bar"; };
};
};
# Logging to AWS CloudWatch
# services.vector = {
# enable = true;
# journaldAccess = true;
# settings = {
# sources.journald = {
# type = "journald";
# # Log only the services we care about
# include_units = ["app.service" "nginx.service" "worker.service"];
# };
# sinks.out = {
# group_name = "CHANGE-ME";
# stream_name = "CHANGE-ME";
# # Change the region to the correct one, e.g. `us-east-1`
# region = "CHANGE-ME";
# auth = {
# access_key_id = "CHANGE-ME";
# secret_access_key = "CHANGE-ME";
# };
# inputs = ["journald"];
# type = "aws_cloudwatch_logs";
# compression = "gzip";
# encoding.codec = "json";
# };
# };
# };
services.ihp = {
domain = "CHANGE-ME.com";
migrations = ./Application/Migration;
schema = ./Application/Schema.sql;
fixtures = ./Application/Fixtures.sql;
sessionSecret = "CHANGE-ME";
# Uncomment to use a custom database URL
# databaseUrl = lib.mkForce "postgresql://postgres:...CHANGE-ME";
additionalEnvVars = {
# Uncomment to use a custom session secret, ensuring sessions aren't invalidated
# on each deploy.
# Learn how to create the secret key in https://ihp.digitallyinduced.com/Guide/deployment.html#ihpsessionsecret
# IHP_SESSION_SECRET = "CHANGE-ME";
SMTP_HOST = "email-smtp.eu-west-1.amazonaws.com";
SMTP_PORT = "587";
SMTP_ENCRYPTION = "STARTTLS";
SMTP_USER = "CHANGE-ME";
SMTP_PASSWORD = "CHANGE-ME";
AWS_ACCESS_KEY_ID = "CHANGE-ME";
AWS_SECRET_ACCESS_KEY = "CHANGE-ME";
};
};
# As we use a pre-built AMI on AWS,
# it is essential to enable automatic updates.
# @see https://nixos.wiki/wiki/Automatic_system_upgrades
system.autoUpgrade.enable = true;
# Keep as is. See https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion
system.stateVersion = "25.05";
}

View File

@@ -0,0 +1,13 @@
# Autogenerated hardware config
# Run 'nixos-generate-config' on the deployment host to generate it
{ config, lib, pkgs, modulesPath, ... }:
{
imports = [
# For AWS EC2: "${inputs.nixpkgs}/nixos/modules/virtualisation/amazon-image.nix"
];
# For testing purposes only, remove on bootable hosts.
boot.loader.grub.enable = pkgs.lib.mkDefault false;
fileSystems."/".device = pkgs.lib.mkDefault "/dev/null";
}

View File

@@ -0,0 +1,6 @@
{ inputs }:
inputs.nixpkgs-nixos.lib.nixosSystem {
system = "x86_64-linux"; # or alternatively: aarch64-linux
specialArgs = inputs // { nixpkgs = inputs.nixpkgs-nixos; };
modules = [ ./configuration.nix ];
}

View File

@@ -0,0 +1,7 @@
# See https://ihp.digitallyinduced.com/Guide/package-management.html
{ ihp, additionalNixpkgsOptions, ... }:
import "${toString ihp}/NixSupport/make-nixpkgs-from-options.nix" {
ihp = ihp;
haskellPackagesDir = ./haskell-packages/.;
additionalNixpkgsOptions = additionalNixpkgsOptions;
}

17
Main.hs Normal file
View File

@@ -0,0 +1,17 @@
module Main where
import IHP.Prelude
import Config
import qualified IHP.Server
import IHP.RouterSupport
import IHP.FrameworkConfig
import IHP.Job.Types
instance FrontController RootApplication where
controllers = []
instance Worker RootApplication where
workers _ = []
main :: IO ()
main = IHP.Server.run config

17
Makefile Normal file
View File

@@ -0,0 +1,17 @@
CSS_FILES += ${IHP}/static/vendor/bootstrap.min.css
CSS_FILES += ${IHP}/static/vendor/flatpickr.min.css
CSS_FILES += static/app.css
JS_FILES += ${IHP}/static/vendor/jquery-3.6.0.slim.min.js
JS_FILES += ${IHP}/static/vendor/timeago.js
JS_FILES += ${IHP}/static/vendor/popper.min.js
JS_FILES += ${IHP}/static/vendor/bootstrap.min.js
JS_FILES += ${IHP}/static/vendor/flatpickr.js
JS_FILES += ${IHP}/static/helpers.js
JS_FILES += ${IHP}/static/vendor/morphdom-umd.min.js
JS_FILES += ${IHP}/static/vendor/turbolinks.js
JS_FILES += ${IHP}/static/vendor/turbolinksInstantClick.js
JS_FILES += ${IHP}/static/vendor/turbolinksMorphdom.js
include ${IHP}/Makefile.dist

2
Setup.hs Normal file
View File

@@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain

23
Test/Integration.hs Normal file
View File

@@ -0,0 +1,23 @@
module Main where
import Test.Hspec
import IHP.Prelude
import IHP.ModelSupport
import IHP.Log.Types
import System.Environment (lookupEnv)
-- Integration tests run with a temporary PostgreSQL database.
-- The DATABASE_URL env var is set automatically by `nix flake check`.
-- See: https://ihp.digitallyinduced.com/Guide/testing.html
main :: IO ()
main = do
databaseUrl <- lookupEnv "DATABASE_URL" >>= \case
Just url -> pure (cs url)
Nothing -> error "DATABASE_URL not set. Run `devenv up` first or use `nix flake check`."
logger <- newLogger def { level = Warn }
withModelContext databaseUrl logger \modelContext -> do
let ?modelContext = modelContext
hspec do
describe "Database" do
it "can execute a query" do
sqlExecDiscardResult "SELECT 1" ()

13
Test/Main.hs Normal file
View File

@@ -0,0 +1,13 @@
module Main where
import Test.Hspec
import IHP.Prelude
-- Import your test specs here:
-- import Test.MySpec
main :: IO ()
main = hspec do
describe "Example" do
it "should pass" do
1 + 1 `shouldBe` (2 :: Int)

9
default.nix Normal file
View File

@@ -0,0 +1,9 @@
# For backwards compatibility using flake.nix
(import
(
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/35bb57c0c8d8b62bbfd284272c928ceb64ddbde9.tar.gz";
sha256 = "sha256:1prd9b1xx8c0sfwnyzkspplh30m613j42l1k789s521f4kv4c2z2";
}
)
{ src = ./.; }).defaultNix

2318
flake.lock generated Normal file

File diff suppressed because it is too large Load Diff

108
flake.nix Normal file
View File

@@ -0,0 +1,108 @@
{
inputs = {
ihp.url = "github:digitallyinduced/ihp/v1.5";
nixpkgs.follows = "ihp/nixpkgs";
nixpkgs-nixos.follows = "ihp/nixpkgs-nixos";
flake-parts.follows = "ihp/flake-parts";
devenv.follows = "ihp/devenv";
systems.follows = "ihp/systems";
devenv-root = {
url = "file+file:///dev/null";
flake = false;
};
};
outputs = inputs@{ self, nixpkgs, nixpkgs-nixos, ihp, flake-parts, systems, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
systems = import systems;
imports = [ ihp.flakeModules.default ];
perSystem = { pkgs, ... }: {
ihp = {
appName = "inter-hub";
enable = true;
projectPath = ./.;
packages = with pkgs; [
# Native dependencies, e.g. imagemagick
];
haskellPackages = p: with p; [
# Haskell dependencies go here
p.ihp
base
wai
text
# ihp-mail # Email support: https://ihp.digitallyinduced.com/Guide/mail.html
# ihp-datasync # Real-time DataSync
# ihp-job-dashboard # Job dashboard UI
# ihp-typed-sql # Type-safe SQL queries
# ihp-pglistener # PostgreSQL LISTEN/NOTIFY
];
devHaskellPackages = p: with p; [
cabal-install
hlint
hspec
ihp-hspec
];
# Hoogle documentation server (enabled by default on port 8002)
# withHoogle = false; # Disable to save memory
# Disable relation type machinery for faster compilation
# relationSupport = false;
# Skip tests/haddock for specific packages to speed up builds
# dontCheckPackages = [ "my-package" ];
# doJailbreakPackages = [ "my-package" ];
# dontHaddockPackages = [ "my-package" ];
# Production build tuning
# optimizationLevel = "2"; # Default: "1", use "2" for more optimized production binaries
# rtsFlags = "-A96m -N"; # GHC runtime flags for compiled binaries
# Mount additional directories under /static/ in production builds
# static.extraDirs = {
# # Frontend = self.packages.${system}.frontend;
# };
# static.makeBundling = true; # Set false if not using Makefile for CSS/JS bundling
};
# Custom configuration that will start with `devenv up`
devenv.shells.default = {
# Start Mailhog on local development to catch outgoing emails
# services.mailhog.enable = true;
# PostgreSQL extensions
# services.postgres.extensions = extensions: [ extensions.postgis ];
# Custom processes that don't appear in https://devenv.sh/reference/options/
processes = {
# Uncomment if you use tailwindcss.
# tailwind.exec = "tailwindcss -c tailwind/tailwind.config.js -i ./tailwind/app.css -o static/app.css --watch=always";
};
};
};
# Adding the new NixOS configuration for "production"
# See https://ihp.digitallyinduced.com/Guide/deployment.html#deploying-with-deploytonixos for more info
# Used to deploy the IHP application
flake.nixosConfigurations."production" = import ./Config/nix/hosts/production/host.nix { inherit inputs; };
};
# The following configuration speeds up build times by using the devenv, cachix and digitallyinduced binary caches
# You can add your own cachix cache here to speed up builds. For that uncomment the following lines and replace `CHANGE-ME` with your cachix cache name
nixConfig = {
extra-substituters = [
"https://devenv.cachix.org"
"https://cachix.cachix.org"
"https://digitallyinduced.cachix.org"
# "https://CHANGE-ME.cachix.org"
];
extra-trusted-public-keys = [
"devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw="
"cachix.cachix.org-1:eWNHQldwUO7G2VkjpnjDbWwy4KQ/HNxht7H4SSoMckM="
"digitallyinduced.cachix.org-1:y+wQvrnxQ+PdEsCt91rmvv39qRCYzEgGQaldK26hCKE="
# "CHANGE-ME.cachix.org-1:CHANGE-ME-PUBLIC-KEY"
];
};
}

4
hie.yaml Normal file
View File

@@ -0,0 +1,4 @@
# Used by haskell-language-server to find GHC settings
cradle:
bios:
shell: "/bin/sh $IHP/.hie-bios"

2
start Executable file
View File

@@ -0,0 +1,2 @@
#!/usr/bin/env bash
devenv up

0
static/app.css Normal file
View File

3
static/app.js Normal file
View File

@@ -0,0 +1,3 @@
$(document).on('ready turbolinks:load', function () {
// This is called on the first page load *and* also when the page is changed by turbolinks
});

0
static/favicon.ico Normal file
View File

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.1 KiB